From a9f7e3dfc59a987c3d6cce4108f18d9f6b72867b Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 4 Feb 2022 18:17:16 +0300 Subject: [PATCH] (un)pad_iso10126 --- 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 +- 7 files changed, 55 insertions(+), 3 deletions(-) diff --git a/README b/README index 97ee0ed..2034715 100644 --- a/README +++ b/README @@ -22,7 +22,7 @@ GOST is GOvernment STandard of Russian Federation (and Soviet Union). * 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 96db53f..eeacd55 100644 --- a/news.texi +++ b/news.texi @@ -3,6 +3,10 @@ @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 7800ed4..38d8dbe 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 93244da..27f0c30 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 @@ def mac_acpkm_master(algo_class, encrypter, key_section_size, section_size, bs, 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 d9d9c96..4cfd694 100644 --- a/pygost/stubs/pygost/gost3413.pyi +++ b/pygost/stubs/pygost/gost3413.pyi @@ -73,3 +73,9 @@ def mac_acpkm_master( 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 2be5595..159f7fe 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 @@ A8 1C 79 A0 4F 29 66 0E A3 FD A8 74 C6 30 79 9E ), 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 a9a2102..329a227 100644 --- a/www.texi +++ b/www.texi @@ -54,7 +54,7 @@ Currently supported algorithms are: (@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) -- 2.44.0