]> Cypherpunks.ru repositories - pygost.git/commitdiff
28147-89 CBC key meshing ability
authorSergey Matveev <stargrave@stargrave.org>
Sun, 2 Dec 2018 17:17:39 +0000 (20:17 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 9 Dec 2018 10:01:32 +0000 (13:01 +0300)
NEWS
news.texi
pygost/gost28147.py
pygost/test_gost28147.py

diff --git a/NEWS b/NEWS
index e2e8679a40c905f310f7d77e6097eddda6d51e58..2655265411dbffa83bcd9c9d7b2a988e71c5700c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 3.13:
     * Ability to explicitly specify used 28147-89 Sbox in
       pygost.wrap.* functions
+    * Ability to use key meshing in 28147-89 CBC mode
 
 3.12:
     * Added mode argument to pygost.gost3410_vko.kek_34102012256,
index 7841bef24b8d6762d19ca13c6e3f578d4596a2ba..e87f63706c9ccfb4f7cbff2c88dc5523329ecf3e 100644 (file)
--- a/news.texi
+++ b/news.texi
@@ -8,6 +8,7 @@
     @itemize
     @item Ability to explicitly specify used 28147-89 Sbox in
         @code{pygost.wrap.*} functions
+    @item Ability to use key meshing in 28147-89 CBC mode
     @end itemize
 
 @anchor{Release 3.12}
index 585d0e7f6866a2215664e06246d591b8664c4e25..78a0e370c1edbafa1185c653359cd9c5b3933b74 100644 (file)
@@ -281,7 +281,7 @@ ecb_encrypt = partial(ecb, action=encrypt)
 ecb_decrypt = partial(ecb, action=decrypt)
 
 
-def cbc_encrypt(key, data, iv=8 * b"\x00", pad=True, sbox=DEFAULT_SBOX):
+def cbc_encrypt(key, data, iv=8 * b"\x00", pad=True, sbox=DEFAULT_SBOX, mesh=False):
     """ CBC encryption mode of operation
 
     :param bytes key: encryption key
@@ -291,6 +291,7 @@ def cbc_encrypt(key, data, iv=8 * b"\x00", pad=True, sbox=DEFAULT_SBOX):
     :type bool pad: perform ISO/IEC 7816-4 padding
     :param sbox: S-box parameters to use
     :type sbox: str, SBOXES'es key
+    :param bool mesh: enable key meshing
     :returns: ciphertext
     :rtype: bytes
 
@@ -307,13 +308,15 @@ def cbc_encrypt(key, data, iv=8 * b"\x00", pad=True, sbox=DEFAULT_SBOX):
         raise ValueError("Data is not blocksize aligned")
     ciphertext = [iv]
     for i in xrange(0, len(data), BLOCKSIZE):
+        if mesh and i >= MESH_MAX_DATA and i % MESH_MAX_DATA == 0:
+            key, _ = meshing(key, iv, sbox=sbox)
         ciphertext.append(ns2block(encrypt(sbox, key, block2ns(
             strxor(ciphertext[-1], data[i:i + BLOCKSIZE])
         ))))
     return b"".join(ciphertext)
 
 
-def cbc_decrypt(key, data, pad=True, sbox=DEFAULT_SBOX):
+def cbc_decrypt(key, data, pad=True, sbox=DEFAULT_SBOX, mesh=False):
     """ CBC decryption mode of operation
 
     :param bytes key: encryption key
@@ -321,6 +324,7 @@ def cbc_decrypt(key, data, pad=True, sbox=DEFAULT_SBOX):
     :type bool pad: perform ISO/IEC 7816-4 unpadding after decryption
     :param sbox: S-box parameters to use
     :type sbox: str, SBOXES'es key
+    :param bool mesh: enable key meshing
     :returns: plaintext
     :rtype: bytes
     """
@@ -330,8 +334,15 @@ def cbc_decrypt(key, data, pad=True, sbox=DEFAULT_SBOX):
         raise ValueError("Data is not blocksize aligned")
     if len(data) < 2 * BLOCKSIZE:
         raise ValueError("There is no either data, or IV in ciphertext")
+    iv = data[:BLOCKSIZE]
     plaintext = []
     for i in xrange(BLOCKSIZE, len(data), BLOCKSIZE):
+        if (
+                mesh and
+                (i - BLOCKSIZE) >= MESH_MAX_DATA and
+                (i - BLOCKSIZE) % MESH_MAX_DATA == 0
+        ):
+            key, _ = meshing(key, iv, sbox=sbox)
         plaintext.append(strxor(
             ns2block(decrypt(sbox, key, block2ns(data[i:i + BLOCKSIZE]))),
             data[i - BLOCKSIZE:i],
index f28618d2c8bbd086a61789c2a2d23ab14ce64675..037b7b86ff643502eccc928774c3eafae6665645 100644 (file)
@@ -338,6 +338,13 @@ class CBCTest(TestCase):
         iv = urandom(8)
         cbc_decrypt(key, cbc_encrypt(key, 8 * b"x", iv))
 
+    def test_meshing(self):
+        pt = urandom(MESH_MAX_DATA * 3)
+        key = urandom(32)
+        ct = cbc_encrypt(key, pt)
+        dt = cbc_decrypt(key, ct)
+        self.assertEqual(pt, dt)
+
 
 class CFBMeshingTest(TestCase):
     def setUp(self):