README | 2 +- news.texi | 4 ++++ pygost/__init__.py | 2 +- pygost/gost3413.py | 25 +++++++++++++++++++++++++ pygost/stubs/pygost/gost3413.pyi | 6 ++++++ pygost/test_gost3413.py | 17 +++++++++++++++++ www.texi | 2 +- diff --git a/README b/README index a992c4c5ae4d274f1d89d7d937d9de6a42564ca6dd5698825ad8771c17118326..5a5dcd267b679d8e078426f8d4a01d4d2b6df67000ed3cc41312bc2d100792f6 100644 --- a/README +++ b/README @@ -22,7 +22,7 @@ * RFC 4491 (using GOST algorithms with X.509) compatibility helpers * GOST R 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) (RFC 7801) * GOST R 34.12-2015 64-bit block cipher Магма (Magma) * GOST R 34.13-2015 padding methods and block cipher modes of operation - (ECB, CTR, OFB, CBC, CFB, MAC) + (ECB, CTR, OFB, CBC, CFB, MAC), ISO 10126 padding * MGM AEAD mode for 64 and 128 bit ciphers (RFC 9058) * CTR-ACPKM, OMAC-ACPKM-Master modes of operation (Р 1323565.1.017-2018) * KExp15/KImp15 key export/import functions (Р 1323565.1.017-2018) diff --git a/news.texi b/news.texi index d93d1aa5fb48eaf1541a92e3e42d7cfb27d5deb3130b6c9f23d3881406ffa441..e8073c7150f8ebc04e7cb90e1449d23b3caa43d294d2108c6cd2ed742d955402 100644 --- a/news.texi +++ b/news.texi @@ -3,6 +3,10 @@ @unnumbered News @table @strong +@anchor{Release 5.10} +@item 5.10 +Added ISO 10126 @code{pygost.gost3413.(un)pad_iso10126} padding support. + @anchor{Release 5.9} @item 5.9 Fixed @code{wrap.wrap_cryptopro}, that ignored Sbox for key diversification. diff --git a/pygost/__init__.py b/pygost/__init__.py index b09257cfdd5e7738f6e43773d6f37c3225891d10a746de8dc266cc7a223c7ec4..cfcf628812a6eb043fd79f5f3b1db35ad1b8b8d34acaf0827e833e7996174b45 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.9" +__version__ = "5.10" diff --git a/pygost/gost3413.py b/pygost/gost3413.py index 8b7879d19bae1cc9e29db852565cb50d65de7f2a06d1fd0993692d8b32079499..df94e00f212d070b7b2c1124bb1738375d724ec4a56cdfd93ba80dcf249669d2 100644 --- a/pygost/gost3413.py +++ b/pygost/gost3413.py @@ -18,6 +18,8 @@ This module currently includes only padding methods. """ +from os import urandom + from pygost.utils import bytes2long from pygost.utils import long2bytes from pygost.utils import strxor @@ -365,3 +367,26 @@ return encrypter(strxor( strxor(pad3(tail, bs), prev), k1 if len(tail) == bs else k2, )) + + +def pad_iso10126(data, blocksize): + """ISO 10126 padding + + Does not exist in 34.13, but added for convenience. + It uses urandom call for getting the randomness. + """ + pad_len = blocksize - len(data) % blocksize + if pad_len == 0: + pad_len = blocksize + return b"".join((data, urandom(pad_len - 1), bytes((pad_len,)))) + + +def unpad_iso10126(data, blocksize): + """Unpad :py:func:`pygost.gost3413.pad_iso10126` + """ + if len(data) % blocksize != 0: + raise ValueError("Data length is not multiple of blocksize") + pad_len = bytearray(data)[-1] + if pad_len > blocksize: + raise ValueError("Padding length is bigger than blocksize") + return data[:-pad_len] diff --git a/pygost/stubs/pygost/gost3413.pyi b/pygost/stubs/pygost/gost3413.pyi index 2674d4074cb2232d8d41ab8e83bd5a54080f9ab240afc92c1b8aea72f5204d11..3a143354a2fe6bdaaf64b06dc444fb64bb7c0052ebcbc451c95451bcb24d749e 100644 --- a/pygost/stubs/pygost/gost3413.pyi +++ b/pygost/stubs/pygost/gost3413.pyi @@ -73,3 +73,9 @@ section_size: int, bs: int, data: bytes, ) -> bytes: ... + + +def pad_iso10126(data: bytes, blocksize: int) -> bytes: ... + + +def unpad_iso10126(data: bytes, blocksize: int) -> bytes: ... diff --git a/pygost/test_gost3413.py b/pygost/test_gost3413.py index 04f3a08c514675922feca9be0e3a7c6f077485f82983f9966754db265b89d9ea..4b212bb900a204ed566fbf7b3d24ec20c9695eb4bf563f5eca4cecb6dd326a76 100644 --- a/pygost/test_gost3413.py +++ b/pygost/test_gost3413.py @@ -36,7 +36,9 @@ from pygost.gost3413 import mac from pygost.gost3413 import mac_acpkm_master from pygost.gost3413 import ofb from pygost.gost3413 import pad2 +from pygost.gost3413 import pad_iso10126 from pygost.gost3413 import unpad2 +from pygost.gost3413 import unpad_iso10126 from pygost.utils import hexdec from pygost.utils import hexenc from pygost.utils import strxor @@ -747,3 +749,18 @@ data=text, ), hexdec("FBB8DCEE45BEA67C35F58C5700898E5D"), ) + + +class ISO10126Test(TestCase): + def test_symmetric(self): + for _ in range(100): + for blocksize in (GOST3412Magma.blocksize, GOST3412Kuznechik.blocksize): + data = urandom(randint(0, blocksize * 3)) + padded = pad_iso10126(data, blocksize) + self.assertSequenceEqual(unpad_iso10126(padded, blocksize), data) + with self.assertRaises(ValueError): + unpad_iso10126(padded[1:], blocksize) + + def test_small(self): + with self.assertRaises(ValueError): + unpad_iso10126(b"foobar\x00\x09", 8) diff --git a/www.texi b/www.texi index c71b373e9ff5da99068ef145dab9d583c1f722f6e5fe21b7883e687af280225a..38caaf8f7cfb7b2488840984a13afc0d8afacbceedca8f1f210f03e4155939b4 100644 --- a/www.texi +++ b/www.texi @@ -54,7 +54,7 @@ @item GOST R 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) (@url{https://tools.ietf.org/html/rfc7801.html, RFC 7801}) @item GOST R 34.12-2015 64-bit block cipher Магма (Magma) @item GOST R 34.13-2015 padding methods and block cipher modes of operation - (ECB, CTR, OFB, CBC, CFB, MAC) + (ECB, CTR, OFB, CBC, CFB, MAC), ISO 10126 padding @item MGM AEAD mode for 64 and 128 bit ciphers (@url{https://tools.ietf.org/html/rfc9058.html, RFC 9058}) @item CTR-ACPKM, OMAC-ACPKM-Master modes of operation (Р 1323565.1.017-2018)