]> Cypherpunks.ru repositories - pygost.git/blob - pygost/test_gost3413.py
Fix 34.13 OFB bug with len(IV) > 2
[pygost.git] / pygost / test_gost3413.py
1 from os import urandom
2 from random import randint
3 from unittest import TestCase
4
5 from pygost.gost3412 import GOST3412Kuznechik
6 from pygost.gost3412 import GOST3412Magma
7 from pygost.gost3413 import _mac_ks
8 from pygost.gost3413 import cbc_decrypt
9 from pygost.gost3413 import cbc_encrypt
10 from pygost.gost3413 import cfb_decrypt
11 from pygost.gost3413 import cfb_encrypt
12 from pygost.gost3413 import ctr
13 from pygost.gost3413 import ecb_decrypt
14 from pygost.gost3413 import ecb_encrypt
15 from pygost.gost3413 import mac
16 from pygost.gost3413 import ofb
17 from pygost.gost3413 import pad2
18 from pygost.gost3413 import unpad2
19 from pygost.utils import hexdec
20 from pygost.utils import hexenc
21 from pygost.utils import strxor
22
23
24 class Pad2Test(TestCase):
25     def test_symmetric(self):
26         for _ in range(100):
27             for blocksize in (8, 16):
28                 data = urandom(randint(0, blocksize * 3))
29                 self.assertSequenceEqual(
30                     unpad2(pad2(data, blocksize), blocksize),
31                     data,
32                 )
33
34
35 class GOST3412KuznechikModesTest(TestCase):
36     key = hexdec("8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef")
37     ciph = GOST3412Kuznechik(key)
38     plaintext = ""
39     plaintext += "1122334455667700ffeeddccbbaa9988"
40     plaintext += "00112233445566778899aabbcceeff0a"
41     plaintext += "112233445566778899aabbcceeff0a00"
42     plaintext += "2233445566778899aabbcceeff0a0011"
43     iv = hexdec("1234567890abcef0a1b2c3d4e5f0011223344556677889901213141516171819")
44
45     def test_ecb_vectors(self):
46         ciphtext = ""
47         ciphtext += "7f679d90bebc24305a468d42b9d4edcd"
48         ciphtext += "b429912c6e0032f9285452d76718d08b"
49         ciphtext += "f0ca33549d247ceef3f5a5313bd4b157"
50         ciphtext += "d0b09ccde830b9eb3a02c4c5aa8ada98"
51         self.assertSequenceEqual(
52             hexenc(ecb_encrypt(self.ciph.encrypt, 16, hexdec(self.plaintext))),
53             ciphtext,
54         )
55         self.assertSequenceEqual(
56             hexenc(ecb_decrypt(self.ciph.decrypt, 16, hexdec(ciphtext))),
57             self.plaintext,
58         )
59
60     def test_ecb_symmetric(self):
61         for _ in range(100):
62             pt = pad2(urandom(randint(0, 16 * 2)), 16)
63             ciph = GOST3412Kuznechik(urandom(32))
64             ct = ecb_encrypt(ciph.encrypt, 16, pt)
65             self.assertSequenceEqual(ecb_decrypt(ciph.decrypt, 16, ct), pt)
66
67     def test_ctr_vectors(self):
68         ciphtext = ""
69         ciphtext += "f195d8bec10ed1dbd57b5fa240bda1b8"
70         ciphtext += "85eee733f6a13e5df33ce4b33c45dee4"
71         ciphtext += "a5eae88be6356ed3d5e877f13564a3a5"
72         ciphtext += "cb91fab1f20cbab6d1c6d15820bdba73"
73         iv = self.iv[:8]
74         self.assertSequenceEqual(
75             hexenc(ctr(self.ciph.encrypt, 16, hexdec(self.plaintext), iv)),
76             ciphtext,
77         )
78         self.assertSequenceEqual(
79             hexenc(ctr(self.ciph.encrypt, 16, hexdec(ciphtext), iv)),
80             self.plaintext,
81         )
82
83     def test_ctr_symmetric(self):
84         for _ in range(100):
85             pt = urandom(randint(0, 16 * 2))
86             iv = urandom(8)
87             ciph = GOST3412Kuznechik(urandom(32))
88             ct = ctr(ciph.encrypt, 16, pt, iv)
89             self.assertSequenceEqual(ctr(ciph.encrypt, 16, ct, iv), pt)
90
91     def test_ofb_vectors(self):
92         ciphtext = ""
93         ciphtext += "81800a59b1842b24ff1f795e897abd95"
94         ciphtext += "ed5b47a7048cfab48fb521369d9326bf"
95         ciphtext += "66a257ac3ca0b8b1c80fe7fc10288a13"
96         ciphtext += "203ebbc066138660a0292243f6903150"
97         self.assertSequenceEqual(
98             hexenc(ofb(self.ciph.encrypt, 16, hexdec(self.plaintext), self.iv)),
99             ciphtext,
100         )
101         self.assertSequenceEqual(
102             hexenc(ofb(self.ciph.encrypt, 16, hexdec(ciphtext), self.iv)),
103             self.plaintext,
104         )
105
106     def test_ofb_symmetric(self):
107         for _ in range(100):
108             pt = urandom(randint(0, 16 * 2))
109             iv = urandom(16 * 2)
110             ciph = GOST3412Kuznechik(urandom(32))
111             ct = ofb(ciph.encrypt, 16, pt, iv)
112             self.assertSequenceEqual(ofb(ciph.encrypt, 16, ct, iv), pt)
113
114     def test_ofb_manual(self):
115         iv = [urandom(16) for _ in range(randint(2, 10))]
116         pt = [urandom(16) for _ in range(len(iv), len(iv) + randint(1, 10))]
117         ciph = GOST3412Kuznechik(urandom(32))
118         r = [ciph.encrypt(i) for i in iv]
119         for i in range(len(pt) - len(iv)):
120             r.append(ciph.encrypt(r[i]))
121         ct = [strxor(g, r) for g, r in zip(pt, r)]
122         self.assertSequenceEqual(
123             ofb(ciph.encrypt, 16, b"".join(pt), b"".join(iv)),
124             b"".join(ct),
125         )
126
127     def test_cbc_vectors(self):
128         ciphtext = ""
129         ciphtext += "689972d4a085fa4d90e52e3d6d7dcc27"
130         ciphtext += "2826e661b478eca6af1e8e448d5ea5ac"
131         ciphtext += "fe7babf1e91999e85640e8b0f49d90d0"
132         ciphtext += "167688065a895c631a2d9a1560b63970"
133         self.assertSequenceEqual(
134             hexenc(cbc_encrypt(self.ciph.encrypt, 16, hexdec(self.plaintext), self.iv)),
135             ciphtext,
136         )
137         self.assertSequenceEqual(
138             hexenc(cbc_decrypt(self.ciph.decrypt, 16, hexdec(ciphtext), self.iv)),
139             self.plaintext,
140         )
141
142     def test_cbc_symmetric(self):
143         for _ in range(100):
144             pt = pad2(urandom(randint(0, 16 * 2)), 16)
145             iv = urandom(16 * 2)
146             ciph = GOST3412Kuznechik(urandom(32))
147             ct = cbc_encrypt(ciph.encrypt, 16, pt, iv)
148             self.assertSequenceEqual(cbc_decrypt(ciph.decrypt, 16, ct, iv), pt)
149
150     def test_cfb_vectors(self):
151         ciphtext = ""
152         ciphtext += "81800a59b1842b24ff1f795e897abd95"
153         ciphtext += "ed5b47a7048cfab48fb521369d9326bf"
154         ciphtext += "79f2a8eb5cc68d38842d264e97a238b5"
155         ciphtext += "4ffebecd4e922de6c75bd9dd44fbf4d1"
156         self.assertSequenceEqual(
157             hexenc(cfb_encrypt(self.ciph.encrypt, 16, hexdec(self.plaintext), self.iv)),
158             ciphtext,
159         )
160         self.assertSequenceEqual(
161             hexenc(cfb_decrypt(self.ciph.encrypt, 16, hexdec(ciphtext), self.iv)),
162             self.plaintext,
163         )
164
165     def test_cfb_symmetric(self):
166         for _ in range(100):
167             pt = urandom(randint(0, 16 * 2))
168             iv = urandom(16 * 2)
169             ciph = GOST3412Kuznechik(urandom(32))
170             ct = cfb_encrypt(ciph.encrypt, 16, pt, iv)
171             self.assertSequenceEqual(cfb_decrypt(ciph.encrypt, 16, ct, iv), pt)
172
173     def test_mac_vectors(self):
174         k1, k2 = _mac_ks(self.ciph.encrypt, 16)
175         self.assertSequenceEqual(hexenc(k1), "297d82bc4d39e3ca0de0573298151dc7")
176         self.assertSequenceEqual(hexenc(k2), "52fb05789a73c7941bc0ae65302a3b8e")
177         self.assertSequenceEqual(
178             hexenc(mac(self.ciph.encrypt, 16, hexdec(self.plaintext))[:8]),
179             "336f4d296059fbe3",
180         )
181
182     def test_mac_applies(self):
183         for _ in range(100):
184             data = urandom(randint(0, 16 * 2))
185             ciph = GOST3412Kuznechik(urandom(32))
186             mac(ciph.encrypt, 16, data)
187
188
189 class GOST3412MagmaModesTest(TestCase):
190     key = hexdec("ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")
191     ciph = GOST3412Magma(key)
192     plaintext = ""
193     plaintext += "92def06b3c130a59"
194     plaintext += "db54c704f8189d20"
195     plaintext += "4a98fb2e67a8024c"
196     plaintext += "8912409b17b57e41"
197     iv = hexdec("1234567890abcdef234567890abcdef134567890abcdef12")
198
199     def test_ecb_vectors(self):
200         ciphtext = ""
201         ciphtext += "2b073f0494f372a0"
202         ciphtext += "de70e715d3556e48"
203         ciphtext += "11d8d9e9eacfbc1e"
204         ciphtext += "7c68260996c67efb"
205         self.assertSequenceEqual(
206             hexenc(ecb_encrypt(self.ciph.encrypt, 8, hexdec(self.plaintext))),
207             ciphtext,
208         )
209         self.assertSequenceEqual(
210             hexenc(ecb_decrypt(self.ciph.decrypt, 8, hexdec(ciphtext))),
211             self.plaintext,
212         )
213
214     def test_ecb_symmetric(self):
215         for _ in range(100):
216             pt = pad2(urandom(randint(0, 16 * 2)), 16)
217             ciph = GOST3412Magma(urandom(32))
218             ct = ecb_encrypt(ciph.encrypt, 8, pt)
219             self.assertSequenceEqual(ecb_decrypt(ciph.decrypt, 8, ct), pt)
220
221     def test_ctr_vectors(self):
222         ciphtext = ""
223         ciphtext += "4e98110c97b7b93c"
224         ciphtext += "3e250d93d6e85d69"
225         ciphtext += "136d868807b2dbef"
226         ciphtext += "568eb680ab52a12d"
227         iv = self.iv[:4]
228         self.assertSequenceEqual(
229             hexenc(ctr(self.ciph.encrypt, 8, hexdec(self.plaintext), iv)),
230             ciphtext,
231         )
232         self.assertSequenceEqual(
233             hexenc(ctr(self.ciph.encrypt, 8, hexdec(ciphtext), iv)),
234             self.plaintext,
235         )
236
237     def test_ctr_symmetric(self):
238         for _ in range(100):
239             pt = urandom(randint(0, 16 * 2))
240             iv = urandom(4)
241             ciph = GOST3412Magma(urandom(32))
242             ct = ctr(ciph.encrypt, 8, pt, iv)
243             self.assertSequenceEqual(ctr(ciph.encrypt, 8, ct, iv), pt)
244
245     def test_ofb_vectors(self):
246         iv = self.iv[:16]
247         ciphtext = ""
248         ciphtext += "db37e0e266903c83"
249         ciphtext += "0d46644c1f9a089c"
250         ciphtext += "a0f83062430e327e"
251         ciphtext += "c824efb8bd4fdb05"
252         self.assertSequenceEqual(
253             hexenc(ofb(self.ciph.encrypt, 8, hexdec(self.plaintext), iv)),
254             ciphtext,
255         )
256         self.assertSequenceEqual(
257             hexenc(ofb(self.ciph.encrypt, 8, hexdec(ciphtext), iv)),
258             self.plaintext,
259         )
260
261     def test_ofb_symmetric(self):
262         for _ in range(100):
263             pt = urandom(randint(0, 16 * 2))
264             iv = urandom(8 * 2)
265             ciph = GOST3412Magma(urandom(32))
266             ct = ofb(ciph.encrypt, 8, pt, iv)
267             self.assertSequenceEqual(ofb(ciph.encrypt, 8, ct, iv), pt)
268
269     def test_cbc_vectors(self):
270         ciphtext = ""
271         ciphtext += "96d1b05eea683919"
272         ciphtext += "aff76129abb937b9"
273         ciphtext += "5058b4a1c4bc0019"
274         ciphtext += "20b78b1a7cd7e667"
275         self.assertSequenceEqual(
276             hexenc(cbc_encrypt(self.ciph.encrypt, 8, hexdec(self.plaintext), self.iv)),
277             ciphtext,
278         )
279         self.assertSequenceEqual(
280             hexenc(cbc_decrypt(self.ciph.decrypt, 8, hexdec(ciphtext), self.iv)),
281             self.plaintext,
282         )
283
284     def test_cbc_symmetric(self):
285         for _ in range(100):
286             pt = pad2(urandom(randint(0, 16 * 2)), 16)
287             iv = urandom(8 * 2)
288             ciph = GOST3412Magma(urandom(32))
289             ct = cbc_encrypt(ciph.encrypt, 8, pt, iv)
290             self.assertSequenceEqual(cbc_decrypt(ciph.decrypt, 8, ct, iv), pt)
291
292     def test_cfb_vectors(self):
293         iv = self.iv[:16]
294         ciphtext = ""
295         ciphtext += "db37e0e266903c83"
296         ciphtext += "0d46644c1f9a089c"
297         ciphtext += "24bdd2035315d38b"
298         ciphtext += "bcc0321421075505"
299         self.assertSequenceEqual(
300             hexenc(cfb_encrypt(self.ciph.encrypt, 8, hexdec(self.plaintext), iv)),
301             ciphtext,
302         )
303         self.assertSequenceEqual(
304             hexenc(cfb_decrypt(self.ciph.encrypt, 8, hexdec(ciphtext), iv)),
305             self.plaintext,
306         )
307
308     def test_cfb_symmetric(self):
309         for _ in range(100):
310             pt = urandom(randint(0, 16 * 2))
311             iv = urandom(8 * 2)
312             ciph = GOST3412Magma(urandom(32))
313             ct = cfb_encrypt(ciph.encrypt, 8, pt, iv)
314             self.assertSequenceEqual(cfb_decrypt(ciph.encrypt, 8, ct, iv), pt)
315
316     def test_mac_vectors(self):
317         k1, k2 = _mac_ks(self.ciph.encrypt, 8)
318         self.assertSequenceEqual(hexenc(k1), "5f459b3342521424")
319         self.assertSequenceEqual(hexenc(k2), "be8b366684a42848")
320         self.assertSequenceEqual(
321             hexenc(mac(self.ciph.encrypt, 8, hexdec(self.plaintext))[:4]),
322             "154e7210",
323         )
324
325     def test_mac_applies(self):
326         for _ in range(100):
327             data = urandom(randint(0, 16 * 2))
328             ciph = GOST3412Magma(urandom(32))
329             mac(ciph.encrypt, 8, data)