]> Cypherpunks.ru repositories - pygost.git/blob - pygost/test_gost341194.py
Shorter module names for convenience and simplicity
[pygost.git] / pygost / test_gost341194.py
1 # coding: utf-8
2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 from unittest import skip
19 from unittest import TestCase
20 import hmac
21
22 from pygost import gost341194
23 from pygost.gost341194 import GOST341194
24 from pygost.utils import bytes2long
25 from pygost.utils import hexenc
26 from pygost.utils import long2bytes
27 from pygost.utils import strxor
28 from pygost.utils import xrange
29
30
31 class TestCopy(TestCase):
32     def runTest(self):
33         m = GOST341194()
34         c = m.copy()
35         m.update(b"foobar")
36         c.update(b"foo")
37         c.update(b"bar")
38         self.assertEqual(m.digest(), c.digest())
39
40
41 class TestHMACPEP247(TestCase):
42     def runTest(self):
43         h = hmac.new(b"foo", digestmod=gost341194)
44         h.update(b"foobar")
45         h.digest()
46
47
48 class TestVectors(TestCase):
49     def test_empty(self):
50         self.assertEqual(
51             GOST341194(b"", "GostR3411_94_TestParamSet").hexdigest(),
52             "ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d",
53         )
54
55     def test_a(self):
56         self.assertEqual(
57             GOST341194(b"a", "GostR3411_94_TestParamSet").hexdigest(),
58             "d42c539e367c66e9c88a801f6649349c21871b4344c6a573f849fdce62f314dd",
59         )
60
61     def test_abc(self):
62         self.assertEqual(
63             GOST341194(b"abc", "GostR3411_94_TestParamSet").hexdigest(),
64             "f3134348c44fb1b2a277729e2285ebb5cb5e0f29c975bc753b70497c06a4d51d",
65         )
66
67     def test_message_digest(self):
68         self.assertEqual(
69             GOST341194(b"message digest", "GostR3411_94_TestParamSet").hexdigest(),
70             "ad4434ecb18f2c99b60cbe59ec3d2469582b65273f48de72db2fde16a4889a4d",
71         )
72
73     def test_Us(self):
74         self.assertEqual(
75             GOST341194(128 * b"U", "GostR3411_94_TestParamSet").hexdigest(),
76             "53a3a3ed25180cef0c1d85a074273e551c25660a87062a52d926a9e8fe5733a4",
77         )
78
79     def test_dog(self):
80         self.assertEqual(
81             GOST341194(b"The quick brown fox jumps over the lazy dog", "GostR3411_94_TestParamSet",).hexdigest(),
82             "77b7fa410c9ac58a25f49bca7d0468c9296529315eaca76bd1a10f376d1f4294",
83         )
84
85     def test_cog(self):
86         self.assertEqual(
87             GOST341194(b"The quick brown fox jumps over the lazy cog", "GostR3411_94_TestParamSet",).hexdigest(),
88             "a3ebc4daaab78b0be131dab5737a7f67e602670d543521319150d2e14eeec445",
89         )
90
91     def test_rfc32(self):
92         self.assertEqual(
93             GOST341194(b"This is message, length=32 bytes", "GostR3411_94_TestParamSet",).hexdigest(),
94             "b1c466d37519b82e8319819ff32595e047a28cb6f83eff1c6916a815a637fffa",
95         )
96
97     def test_rfc50(self):
98         self.assertEqual(
99             GOST341194(b"Suppose the original message has length = 50 bytes", "GostR3411_94_TestParamSet",).hexdigest(),
100             "471aba57a60a770d3a76130635c1fbea4ef14de51f78b4ae57dd893b62f55208",
101         )
102
103
104 class TestVectorsCryptoPro(TestCase):
105     """ CryptoPro S-box test vectors
106     """
107     def test_empty(self):
108         self.assertEqual(
109             GOST341194(b"", "GostR3411_94_CryptoProParamSet").hexdigest(),
110             "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0",
111         )
112
113     def test_a(self):
114         self.assertEqual(
115             GOST341194(b"a", "GostR3411_94_CryptoProParamSet").hexdigest(),
116             "e74c52dd282183bf37af0079c9f78055715a103f17e3133ceff1aacf2f403011",
117         )
118
119     def test_abc(self):
120         self.assertEqual(
121             GOST341194(b"abc", "GostR3411_94_CryptoProParamSet").hexdigest(),
122             "b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c",
123         )
124
125     def test_message_digest(self):
126         self.assertEqual(
127             GOST341194(b"message digest", "GostR3411_94_CryptoProParamSet",).hexdigest(),
128             "bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0",
129         )
130
131     def test_dog(self):
132         self.assertEqual(
133             GOST341194(b"The quick brown fox jumps over the lazy dog", "GostR3411_94_CryptoProParamSet",).hexdigest(),
134             "9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76",
135         )
136
137     def test_32(self):
138         self.assertEqual(
139             GOST341194(b"This is message, length=32 bytes", "GostR3411_94_CryptoProParamSet",).hexdigest(),
140             "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb",
141         )
142
143     def test_50(self):
144         self.assertEqual(
145             GOST341194(b"Suppose the original message has length = 50 bytes", "GostR3411_94_CryptoProParamSet",).hexdigest(),
146             "c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011",
147         )
148
149     def test_Us(self):
150         self.assertEqual(
151             GOST341194(128 * b"U", "GostR3411_94_CryptoProParamSet").hexdigest(),
152             "1c4ac7614691bbf427fa2316216be8f10d92edfd37cd1027514c1008f649c4e8",
153         )
154
155
156 # This implementation is based on Python 3.5.2 source code.
157 # PyGOST does not register itself in hashlib anyway, so use
158 # pbkdf2_hmac directly.
159 def pbkdf2_hmac(password, salt, iterations, dklen):
160     inner = GOST341194(sbox="GostR3411_94_CryptoProParamSet")
161     outer = GOST341194(sbox="GostR3411_94_CryptoProParamSet")
162     password = password + b'\x00' * (inner.block_size - len(password))
163     inner.update(strxor(password, len(password) * b"\x36"))
164     outer.update(strxor(password, len(password) * b"\x5C"))
165
166     def prf(msg):
167         icpy = inner.copy()
168         ocpy = outer.copy()
169         icpy.update(msg)
170         ocpy.update(icpy.digest())
171         return ocpy.digest()
172
173     dkey = b''
174     loop = 1
175     while len(dkey) < dklen:
176         prev = prf(salt + long2bytes(loop, 4))
177         rkey = bytes2long(prev)
178         for _ in xrange(iterations - 1):
179             prev = prf(prev)
180             rkey ^= bytes2long(prev)
181         loop += 1
182         dkey += long2bytes(rkey, inner.digest_size)
183     return dkey[:dklen]
184
185
186 class TestPBKDF2(TestCase):
187     """http://tc26.ru/methods/containers_v1/Addition_to_PKCS5_v1_0.pdf test vectors
188     """
189     def test_1(self):
190         self.assertEqual(
191             hexenc(pbkdf2_hmac(b"password", b"salt", 1, 32)),
192             "7314e7c04fb2e662c543674253f68bd0b73445d07f241bed872882da21662d58",
193         )
194
195     def test_2(self):
196         self.assertEqual(
197             hexenc(pbkdf2_hmac(b"password", b"salt", 2, 32)),
198             "990dfa2bd965639ba48b07b792775df79f2db34fef25f274378872fed7ed1bb3",
199         )
200
201     def test_3(self):
202         self.assertEqual(
203             hexenc(pbkdf2_hmac(b"password", b"salt", 4096, 32)),
204             "1f1829a94bdff5be10d0aeb36af498e7a97467f3b31116a5a7c1afff9deadafe",
205         )
206
207     @skip("it takes too long")
208     def test_4(self):
209         self.assertEqual(
210             hexenc(pbkdf2_hmac(b"password", b"salt", 16777216, 32)),
211             "a57ae5a6088396d120850c5c09de0a525100938a59b1b5c3f7810910d05fcd97",
212         )
213
214     def test_5(self):
215         self.assertEqual(
216             hexenc(pbkdf2_hmac(
217                 b"passwordPASSWORDpassword",
218                 b"saltSALTsaltSALTsaltSALTsaltSALTsalt",
219                 4096,
220                 40,
221             )),
222             "788358c69cb2dbe251a7bb17d5f4241f265a792a35becde8d56f326b49c85047b7638acb4764b1fd",
223         )
224
225     def test_6(self):
226         self.assertEqual(
227             hexenc(pbkdf2_hmac(
228                 b"pass\x00word",
229                 b"sa\x00lt",
230                 4096,
231                 20,
232             )),
233             "43e06c5590b08c0225242373127edf9c8e9c3291",
234         )