X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=pygost%2Fgost3410.py;h=a3e2f7ad8c316458ee8916398842c6dde1af1f07;hb=3d854c61b4a7446ccf8d4b1b6cfd2297d81d6b07;hp=b518c95707b48c9d0f3c0741a25a2845c90b2ac0;hpb=82af8726ef5d5e2752089a45750e56c9910398c7;p=pygost.git diff --git a/pygost/gost3410.py b/pygost/gost3410.py index b518c95..a3e2f7a 100644 --- a/pygost/gost3410.py +++ b/pygost/gost3410.py @@ -1,6 +1,6 @@ # coding: utf-8 # PyGOST -- Pure Python GOST cryptographic functions library -# Copyright (C) 2015-2020 Sergey Matveev +# Copyright (C) 2015-2021 Sergey Matveev # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -""" GOST R 34.10 public-key signature function. +"""GOST R 34.10 public-key signature function. This is implementation of GOST R 34.10-2001 (:rfc:`5832`), GOST R 34.10-2012 (:rfc:`7091`). The difference between 2001 and 2012 is the @@ -35,7 +35,7 @@ def point_size(point): class GOST3410Curve(object): - """ GOST 34.10 validated curve + """GOST 34.10 validated curve >>> curve = CURVES["id-GostR3410-2001-TestParamSet"] >>> prv = prv_unmarshal(urandom(32)) @@ -53,8 +53,9 @@ class GOST3410Curve(object): the canonical form :param long e, d: coefficients of the equation of the elliptic curve in the twisted Edwards form + :param str name: human-readable curve name """ - def __init__(self, p, q, a, b, x, y, cofactor=1, e=None, d=None): + def __init__(self, p, q, a, b, x, y, cofactor=1, e=None, d=None, name=None): self.p = p self.q = q self.a = a @@ -64,16 +65,18 @@ class GOST3410Curve(object): self.cofactor = cofactor self.e = e self.d = d - r1 = self.y * self.y % self.p - r2 = ((self.x * self.x + self.a) * self.x + self.b) % self.p - if r1 != self.pos(r2): + if not self.contains((x, y)): raise ValueError("Invalid parameters") self._st = None + self.name = name @property def point_size(self): return point_size(self.p) + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.name) + def pos(self, v): """Make positive number """ @@ -81,6 +84,16 @@ class GOST3410Curve(object): return v + self.p return v + def contains(self, point): + """Is point on the curve? + + :type point: (long, long) + """ + x, y = point + r1 = y * y % self.p + r2 = ((x * x + self.a) * x + self.b) % self.p + return r1 == self.pos(r2) + def _add(self, p1x, p1y, p2x, p2y): if p1x == p2x and p1y == p2y: # double @@ -112,7 +125,7 @@ class GOST3410Curve(object): """Compute s/t parameters for twisted Edwards curve points conversion """ if self.e is None or self.d is None: - raise ValueError("non twisted Edwards curve") + raise ValueError("Non twisted Edwards curve") if self._st is not None: return self._st self._st = ( @@ -139,7 +152,18 @@ CURVES = { x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")), y=bytes2long(hexdec("08E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8")), ), - "id-GostR3410-2001-CryptoPro-A-ParamSet": GOST3410Curve( + "id-tc26-gost-3410-12-256-paramSetA": GOST3410Curve( + p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")), + q=bytes2long(hexdec("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67")), + a=bytes2long(hexdec("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335")), + b=bytes2long(hexdec("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513")), + x=bytes2long(hexdec("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28")), + y=bytes2long(hexdec("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C")), + cofactor=4, + e=0x01, + d=bytes2long(hexdec("0605F6B7C183FA81578BC39CFAD518132B9DF62897009AF7E522C32D6DC7BFFB")), + ), + "id-tc26-gost-3410-12-256-paramSetB": GOST3410Curve( p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")), q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893")), a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94")), @@ -147,7 +171,7 @@ CURVES = { x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")), y=bytes2long(hexdec("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14")), ), - "id-GostR3410-2001-CryptoPro-B-ParamSet": GOST3410Curve( + "id-tc26-gost-3410-12-256-paramSetC": GOST3410Curve( p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C99")), q=bytes2long(hexdec("800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F")), a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C96")), @@ -155,7 +179,7 @@ CURVES = { x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")), y=bytes2long(hexdec("3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC")), ), - "id-GostR3410-2001-CryptoPro-C-ParamSet": GOST3410Curve( + "id-tc26-gost-3410-12-256-paramSetD": GOST3410Curve( p=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B")), q=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9")), a=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598")), @@ -163,18 +187,7 @@ CURVES = { x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000000")), y=bytes2long(hexdec("41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67")), ), - "id-tc26-gost-3410-2012-256-paramSetA": GOST3410Curve( - p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")), - q=bytes2long(hexdec("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67")), - a=bytes2long(hexdec("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335")), - b=bytes2long(hexdec("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513")), - x=bytes2long(hexdec("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28")), - y=bytes2long(hexdec("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C")), - cofactor=4, - e=0x01, - d=bytes2long(hexdec("0605F6B7C183FA81578BC39CFAD518132B9DF62897009AF7E522C32D6DC7BFFB")), - ), - "id-tc26-gost-3410-2012-512-paramSetTest": GOST3410Curve( + "id-tc26-gost-3410-12-512-paramSetTest": GOST3410Curve( p=bytes2long(hexdec("4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DF1D852741AF4704A0458047E80E4546D35B8336FAC224DD81664BBF528BE6373")), q=bytes2long(hexdec("4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DA82F2D7ECB1DBAC719905C5EECC423F1D86E25EDBE23C595D644AAF187E6E6DF")), a=7, @@ -198,7 +211,7 @@ CURVES = { x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")), y=bytes2long(hexdec("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD")), ), - "id-tc26-gost-3410-2012-512-paramSetC": GOST3410Curve( + "id-tc26-gost-3410-12-512-paramSetC": GOST3410Curve( p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")), q=bytes2long(hexdec("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED")), a=bytes2long(hexdec("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3")), @@ -210,16 +223,26 @@ CURVES = { d=bytes2long(hexdec("9E4F5D8C017D8D9F13A5CF3CDF5BFE4DAB402D54198E31EBDE28A0621050439CA6B39E0A515C06B304E2CE43E79E369E91A0CFC2BC2A22B4CA302DBB33EE7550")), ), } +CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] = CURVES["id-tc26-gost-3410-12-256-paramSetB"] +CURVES["id-GostR3410-2001-CryptoPro-B-ParamSet"] = CURVES["id-tc26-gost-3410-12-256-paramSetC"] +CURVES["id-GostR3410-2001-CryptoPro-C-ParamSet"] = CURVES["id-tc26-gost-3410-12-256-paramSetD"] CURVES["id-GostR3410-2001-CryptoPro-XchA-ParamSet"] = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] CURVES["id-GostR3410-2001-CryptoPro-XchB-ParamSet"] = CURVES["id-GostR3410-2001-CryptoPro-C-ParamSet"] -CURVES["id-tc26-gost-3410-2012-256-paramSetB"] = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] -CURVES["id-tc26-gost-3410-2012-256-paramSetC"] = CURVES["id-GostR3410-2001-CryptoPro-B-ParamSet"] -CURVES["id-tc26-gost-3410-2012-256-paramSetD"] = CURVES["id-GostR3410-2001-CryptoPro-C-ParamSet"] -DEFAULT_CURVE = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] +CURVES["id-tc26-gost-3410-2012-256-paramSetA"] = CURVES["id-tc26-gost-3410-12-256-paramSetA"] +CURVES["id-tc26-gost-3410-2012-256-paramSetB"] = CURVES["id-tc26-gost-3410-12-256-paramSetB"] +CURVES["id-tc26-gost-3410-2012-256-paramSetC"] = CURVES["id-tc26-gost-3410-12-256-paramSetC"] +CURVES["id-tc26-gost-3410-2012-256-paramSetD"] = CURVES["id-tc26-gost-3410-12-256-paramSetD"] +CURVES["id-tc26-gost-3410-2012-512-paramSetTest"] = CURVES["id-tc26-gost-3410-12-512-paramSetTest"] +CURVES["id-tc26-gost-3410-2012-512-paramSetA"] = CURVES["id-tc26-gost-3410-12-512-paramSetA"] +CURVES["id-tc26-gost-3410-2012-512-paramSetB"] = CURVES["id-tc26-gost-3410-12-512-paramSetB"] +CURVES["id-tc26-gost-3410-2012-512-paramSetC"] = CURVES["id-tc26-gost-3410-12-512-paramSetC"] +for _name, _curve in CURVES.items(): + _curve.name = _name +DEFAULT_CURVE = CURVES["id-tc26-gost-3410-12-256-paramSetB"] def public_key(curve, prv): - """ Generate public key from the private one + """Generate public key from the private one :param GOST3410Curve curve: curve to use :param long prv: private key @@ -230,7 +253,7 @@ def public_key(curve, prv): def sign(curve, prv, digest, rand=None): - """ Calculate signature for provided digest + """Calculate signature for provided digest :param GOST3410Curve curve: curve to use :param long prv: private key @@ -268,7 +291,7 @@ def sign(curve, prv, digest, rand=None): def verify(curve, pub, digest, signature): - """ Verify provided digest with the signature + """Verify provided digest with the signature :param GOST3410Curve curve: curve to use :type pub: (long, long) @@ -316,10 +339,26 @@ def prv_unmarshal(prv): :param bytes prv: serialized private key :rtype: long + + It is advisable to use :py:func:`pygost.gost3410.prv_marshal` to + assure that key i in curve's Q field for better compatibility with + some implementations. """ return bytes2long(prv[::-1]) +def prv_marshal(curve, prv): + """Marshal little-endian private key + + :param GOST3410Curve curve: curve to use + :param long prv: serialized private key + :rtype: bytes + + Key is in curve's Q field. + """ + return long2bytes(prv % curve.q, point_size(prv))[::-1] + + def pub_marshal(pub): """Marshal public key