X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=pygost%2Fgost3410.py;h=58a20e0fe7c6a06020dc90c34e80c76ca78b0150;hb=9ab3b1d03f734f4aae28364f7a6c7c7c223b30a9;hp=b518c95707b48c9d0f3c0741a25a2845c90b2ac0;hpb=82af8726ef5d5e2752089a45750e56c9910398c7;p=pygost.git diff --git a/pygost/gost3410.py b/pygost/gost3410.py index b518c95..58a20e0 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)) @@ -64,9 +64,7 @@ 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 @@ -81,6 +79,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 +120,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 = ( @@ -219,7 +227,7 @@ DEFAULT_CURVE = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] 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 +238,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 +276,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 +324,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