README | 2 ++ news.texi | 5 +++++ pygost/__init__.py | 2 +- pygost/gost3410.py | 16 ++++++++++++++++ pygost/stubs/pygost/gost3410.pyi | 3 +++ pygost/test_gost3410.py | 8 +++++--- diff --git a/README b/README index de5ca5fe42bc2ae756afc4292e1c7a99eb489d515a8f9dac337d50e46a280bf3..2f025ec46d603f48a1dc7f7a86517532f1a93af4dfc1b8c5182c1899c1f61349 100644 --- a/README +++ b/README @@ -39,7 +39,9 @@ >>> curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"] >>> from os import urandom >>> prv_raw = urandom(64) >>> from pygost.gost3410 import prv_unmarshal + >>> from pygost.gost3410 import prv_marshal >>> prv = prv_unmarshal(prv_raw) + >>> prv_raw = prv_marshal(curve, prv) >>> from pygost.gost3410 import public_key >>> pub = public_key(curve, prv) >>> from pygost.gost3410 import pub_marshal diff --git a/news.texi b/news.texi index 23d369cf031ea06070743486646ffb8dbc1cb025ebabfe82eb3af3a32737350c..bd99b4081c16d2dfc76ab7a2dd7bb81cb7c35a91c7712fb3ff317d2ef66be68e 100644 --- a/news.texi +++ b/news.texi @@ -3,6 +3,11 @@ @unnumbered News @table @strong +@anchor{Release 5.4} +@item 5.4 +@item @code{gost3410.prv_marshal} helper can make private keys that are +in curve's Q field, for better compatibility with some implementations. + @anchor{Release 5.3} @item 5.3 @itemize diff --git a/pygost/__init__.py b/pygost/__init__.py index c1e43a5fe7109eb25b761cc0ff3b7a1067497b401c696107557bf668c14dd56e..3be0a5cf7b60ee6e473b355ad95b44f8bb8cdc3dd6be1fa5f54bbe44afa4c302 100644 --- a/pygost/__init__.py +++ b/pygost/__init__.py @@ -3,4 +3,4 @@ PyGOST is free software: see the file COPYING for copying conditions. """ -__version__ = "5.3" +__version__ = "5.4" diff --git a/pygost/gost3410.py b/pygost/gost3410.py index f320c3f7ff82b58c7bfda7a539e9206d9fa94943ae51e8a2f2bbd4762312e7cb..2a079b70dc31a12b95280f63061cda8c7fcfccfe32679bc565b6e3e0838a40da 100644 --- a/pygost/gost3410.py +++ b/pygost/gost3410.py @@ -324,8 +324,24 @@ """Unmarshal little-endian private key :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): diff --git a/pygost/stubs/pygost/gost3410.pyi b/pygost/stubs/pygost/gost3410.pyi index a347458e7a75be2c9c0b6b015fd1e53fcc75dcd161d1bd9b414033e54d261228..3069a24a941c468411a0c6d5a08ff407f60ea84a1707c32c6255c21af445a720 100644 --- a/pygost/stubs/pygost/gost3410.pyi +++ b/pygost/stubs/pygost/gost3410.pyi @@ -55,6 +55,9 @@ def prv_unmarshal(prv: bytes) -> int: ... +def prv_marshal(curve: GOST3410Curve, prv: int) -> bytes: ... + + def pub_marshal(pub: PublicKey) -> bytes: ... diff --git a/pygost/test_gost3410.py b/pygost/test_gost3410.py index d000cd4624e32327d9daa8159ad6542ae0ac894518a8579af76bb5fbff716d34..a1a8f303cdae49a8e351f56730a6a41ae885439da9756a877faf5de4678c7218 100644 --- a/pygost/test_gost3410.py +++ b/pygost/test_gost3410.py @@ -19,6 +19,8 @@ from unittest import TestCase from pygost.gost3410 import CURVES from pygost.gost3410 import GOST3410Curve +from pygost.gost3410 import prv_marshal +from pygost.gost3410 import prv_unmarshal from pygost.gost3410 import public_key from pygost.gost3410 import sign from pygost.gost3410 import uv2xy @@ -81,8 +83,8 @@ self.assertTrue(verify(c, (pubX, pubY), digest, signature)) def test_sequence(self): c = CURVES["id-GostR3410-2001-TestParamSet"] - prv = bytes2long(urandom(32)) - pubX, pubY = public_key(c, prv) + prv = prv_unmarshal(urandom(32)) + pubX, pubY = public_key(c, prv_unmarshal(prv_marshal(c, prv))) for _ in range(20): digest = urandom(32) s = sign(c, prv, digest) @@ -255,7 +257,7 @@ def test_sequence(self): c = CURVES["id-tc26-gost-3410-12-512-paramSetA"] prv = bytes2long(urandom(64)) - pubX, pubY = public_key(c, prv) + pubX, pubY = public_key(c, prv_unmarshal(prv_marshal(c, prv))) for _ in range(20): digest = urandom(64) s = sign(c, prv, digest)