2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
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.
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.
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/>.
18 from os import urandom
19 from unittest import TestCase
21 from pygost.gost3410 import CURVE_PARAMS
22 from pygost.gost3410 import GOST3410Curve
23 from pygost.gost3410 import kek
24 from pygost.gost3410 import public_key
25 from pygost.gost3410 import sign
26 from pygost.gost3410 import SIZE_3410_2001
27 from pygost.gost3410 import SIZE_3410_2012
28 from pygost.gost3410 import verify
29 from pygost.utils import bytes2long
30 from pygost.utils import long2bytes
33 class Test341001(TestCase):
35 """ Test vector from :rfc:`5832`
37 private_key = bytes(bytearray((
38 0x7A, 0x92, 0x9A, 0xDE, 0x78, 0x9B, 0xB9, 0xBE,
39 0x10, 0xED, 0x35, 0x9D, 0xD3, 0x9A, 0x72, 0xC1,
40 0x1B, 0x60, 0x96, 0x1F, 0x49, 0x39, 0x7E, 0xEE,
41 0x1D, 0x19, 0xCE, 0x98, 0x91, 0xEC, 0x3B, 0x28
43 public_key_x = bytes(bytearray((
44 0x7F, 0x2B, 0x49, 0xE2, 0x70, 0xDB, 0x6D, 0x90,
45 0xD8, 0x59, 0x5B, 0xEC, 0x45, 0x8B, 0x50, 0xC5,
46 0x85, 0x85, 0xBA, 0x1D, 0x4E, 0x9B, 0x78, 0x8F,
47 0x66, 0x89, 0xDB, 0xD8, 0xE5, 0x6F, 0xD8, 0x0B
49 public_key_y = bytes(bytearray((
50 0x26, 0xF1, 0xB4, 0x89, 0xD6, 0x70, 0x1D, 0xD1,
51 0x85, 0xC8, 0x41, 0x3A, 0x97, 0x7B, 0x3C, 0xBB,
52 0xAF, 0x64, 0xD1, 0xC5, 0x93, 0xD2, 0x66, 0x27,
53 0xDF, 0xFB, 0x10, 0x1A, 0x87, 0xFF, 0x77, 0xDA
55 digest = bytes(bytearray((
56 0x2D, 0xFB, 0xC1, 0xB3, 0x72, 0xD8, 0x9A, 0x11,
57 0x88, 0xC0, 0x9C, 0x52, 0xE0, 0xEE, 0xC6, 0x1F,
58 0xCE, 0x52, 0x03, 0x2A, 0xB1, 0x02, 0x2E, 0x8E,
59 0x67, 0xEC, 0xE6, 0x67, 0x2B, 0x04, 0x3E, 0xE5
61 signature = bytes(bytearray((
62 0x41, 0xAA, 0x28, 0xD2, 0xF1, 0xAB, 0x14, 0x82,
63 0x80, 0xCD, 0x9E, 0xD5, 0x6F, 0xED, 0xA4, 0x19,
64 0x74, 0x05, 0x35, 0x54, 0xA4, 0x27, 0x67, 0xB8,
65 0x3A, 0xD0, 0x43, 0xFD, 0x39, 0xDC, 0x04, 0x93,
66 0x01, 0x45, 0x6C, 0x64, 0xBA, 0x46, 0x42, 0xA1,
67 0x65, 0x3C, 0x23, 0x5A, 0x98, 0xA6, 0x02, 0x49,
68 0xBC, 0xD6, 0xD3, 0xF7, 0x46, 0xB6, 0x31, 0xDF,
69 0x92, 0x80, 0x14, 0xF6, 0xC5, 0xBF, 0x9C, 0x40
71 private_key = bytes2long(private_key)
72 signature = signature[32:] + signature[:32]
74 c = GOST3410Curve(*CURVE_PARAMS["GostR3410_2001_TestParamSet"])
75 pubX, pubY = public_key(c, private_key)
76 self.assertEqual(long2bytes(pubX), public_key_x)
77 self.assertEqual(long2bytes(pubY), public_key_y)
78 s = sign(c, private_key, digest)
79 self.assertTrue(verify(c, pubX, pubY, digest, s))
80 self.assertTrue(verify(c, pubX, pubY, digest, signature))
82 def test_sequence(self):
83 c = GOST3410Curve(*CURVE_PARAMS['GostR3410_2001_TestParamSet'])
84 private_key = bytes2long(urandom(32))
85 pubX, pubY = public_key(c, private_key)
88 s = sign(c, private_key, digest, size=SIZE_3410_2001)
89 self.assertTrue(verify(c, pubX, pubY, digest, s, size=SIZE_3410_2001))
92 class Test34102012(TestCase):
94 """ Test vector from libgcl3
97 0x45, 0x31, 0xAC, 0xD1, 0xFE, 0x00, 0x23, 0xC7,
98 0x55, 0x0D, 0x26, 0x7B, 0x6B, 0x2F, 0xEE, 0x80,
99 0x92, 0x2B, 0x14, 0xB2, 0xFF, 0xB9, 0x0F, 0x04,
100 0xD4, 0xEB, 0x7C, 0x09, 0xB5, 0xD2, 0xD1, 0x5D,
101 0xF1, 0xD8, 0x52, 0x74, 0x1A, 0xF4, 0x70, 0x4A,
102 0x04, 0x58, 0x04, 0x7E, 0x80, 0xE4, 0x54, 0x6D,
103 0x35, 0xB8, 0x33, 0x6F, 0xAC, 0x22, 0x4D, 0xD8,
104 0x16, 0x64, 0xBB, 0xF5, 0x28, 0xBE, 0x63, 0x73
106 q = bytes(bytearray((
107 0x45, 0x31, 0xAC, 0xD1, 0xFE, 0x00, 0x23, 0xC7,
108 0x55, 0x0D, 0x26, 0x7B, 0x6B, 0x2F, 0xEE, 0x80,
109 0x92, 0x2B, 0x14, 0xB2, 0xFF, 0xB9, 0x0F, 0x04,
110 0xD4, 0xEB, 0x7C, 0x09, 0xB5, 0xD2, 0xD1, 0x5D,
111 0xA8, 0x2F, 0x2D, 0x7E, 0xCB, 0x1D, 0xBA, 0xC7,
112 0x19, 0x90, 0x5C, 0x5E, 0xEC, 0xC4, 0x23, 0xF1,
113 0xD8, 0x6E, 0x25, 0xED, 0xBE, 0x23, 0xC5, 0x95,
114 0xD6, 0x44, 0xAA, 0xF1, 0x87, 0xE6, 0xE6, 0xDF
116 a = bytes(bytearray((
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07
126 b = bytes(bytearray((
127 0x1C, 0xFF, 0x08, 0x06, 0xA3, 0x11, 0x16, 0xDA,
128 0x29, 0xD8, 0xCF, 0xA5, 0x4E, 0x57, 0xEB, 0x74,
129 0x8B, 0xC5, 0xF3, 0x77, 0xE4, 0x94, 0x00, 0xFD,
130 0xD7, 0x88, 0xB6, 0x49, 0xEC, 0xA1, 0xAC, 0x43,
131 0x61, 0x83, 0x40, 0x13, 0xB2, 0xAD, 0x73, 0x22,
132 0x48, 0x0A, 0x89, 0xCA, 0x58, 0xE0, 0xCF, 0x74,
133 0xBC, 0x9E, 0x54, 0x0C, 0x2A, 0xDD, 0x68, 0x97,
134 0xFA, 0xD0, 0xA3, 0x08, 0x4F, 0x30, 0x2A, 0xDC
136 x = bytes(bytearray((
137 0x24, 0xD1, 0x9C, 0xC6, 0x45, 0x72, 0xEE, 0x30,
138 0xF3, 0x96, 0xBF, 0x6E, 0xBB, 0xFD, 0x7A, 0x6C,
139 0x52, 0x13, 0xB3, 0xB3, 0xD7, 0x05, 0x7C, 0xC8,
140 0x25, 0xF9, 0x10, 0x93, 0xA6, 0x8C, 0xD7, 0x62,
141 0xFD, 0x60, 0x61, 0x12, 0x62, 0xCD, 0x83, 0x8D,
142 0xC6, 0xB6, 0x0A, 0xA7, 0xEE, 0xE8, 0x04, 0xE2,
143 0x8B, 0xC8, 0x49, 0x97, 0x7F, 0xAC, 0x33, 0xB4,
144 0xB5, 0x30, 0xF1, 0xB1, 0x20, 0x24, 0x8A, 0x9A
146 y = bytes(bytearray((
147 0x2B, 0xB3, 0x12, 0xA4, 0x3B, 0xD2, 0xCE, 0x6E,
148 0x0D, 0x02, 0x06, 0x13, 0xC8, 0x57, 0xAC, 0xDD,
149 0xCF, 0xBF, 0x06, 0x1E, 0x91, 0xE5, 0xF2, 0xC3,
150 0xF3, 0x24, 0x47, 0xC2, 0x59, 0xF3, 0x9B, 0x2C,
151 0x83, 0xAB, 0x15, 0x6D, 0x77, 0xF1, 0x49, 0x6B,
152 0xF7, 0xEB, 0x33, 0x51, 0xE1, 0xEE, 0x4E, 0x43,
153 0xDC, 0x1A, 0x18, 0xB9, 0x1B, 0x24, 0x64, 0x0B,
154 0x6D, 0xBB, 0x92, 0xCB, 0x1A, 0xDD, 0x37, 0x1E
156 private_key = bytes(bytearray((
157 0x0B, 0xA6, 0x04, 0x8A, 0xAD, 0xAE, 0x24, 0x1B,
158 0xA4, 0x09, 0x36, 0xD4, 0x77, 0x56, 0xD7, 0xC9,
159 0x30, 0x91, 0xA0, 0xE8, 0x51, 0x46, 0x69, 0x70,
160 0x0E, 0xE7, 0x50, 0x8E, 0x50, 0x8B, 0x10, 0x20,
161 0x72, 0xE8, 0x12, 0x3B, 0x22, 0x00, 0xA0, 0x56,
162 0x33, 0x22, 0xDA, 0xD2, 0x82, 0x7E, 0x27, 0x14,
163 0xA2, 0x63, 0x6B, 0x7B, 0xFD, 0x18, 0xAA, 0xDF,
164 0xC6, 0x29, 0x67, 0x82, 0x1F, 0xA1, 0x8D, 0xD4
166 public_key_x = bytes(bytearray((
167 0x11, 0x5D, 0xC5, 0xBC, 0x96, 0x76, 0x0C, 0x7B,
168 0x48, 0x59, 0x8D, 0x8A, 0xB9, 0xE7, 0x40, 0xD4,
169 0xC4, 0xA8, 0x5A, 0x65, 0xBE, 0x33, 0xC1, 0x81,
170 0x5B, 0x5C, 0x32, 0x0C, 0x85, 0x46, 0x21, 0xDD,
171 0x5A, 0x51, 0x58, 0x56, 0xD1, 0x33, 0x14, 0xAF,
172 0x69, 0xBC, 0x5B, 0x92, 0x4C, 0x8B, 0x4D, 0xDF,
173 0xF7, 0x5C, 0x45, 0x41, 0x5C, 0x1D, 0x9D, 0xD9,
174 0xDD, 0x33, 0x61, 0x2C, 0xD5, 0x30, 0xEF, 0xE1
176 public_key_y = bytes(bytearray((
177 0x37, 0xC7, 0xC9, 0x0C, 0xD4, 0x0B, 0x0F, 0x56,
178 0x21, 0xDC, 0x3A, 0xC1, 0xB7, 0x51, 0xCF, 0xA0,
179 0xE2, 0x63, 0x4F, 0xA0, 0x50, 0x3B, 0x3D, 0x52,
180 0x63, 0x9F, 0x5D, 0x7F, 0xB7, 0x2A, 0xFD, 0x61,
181 0xEA, 0x19, 0x94, 0x41, 0xD9, 0x43, 0xFF, 0xE7,
182 0xF0, 0xC7, 0x0A, 0x27, 0x59, 0xA3, 0xCD, 0xB8,
183 0x4C, 0x11, 0x4E, 0x1F, 0x93, 0x39, 0xFD, 0xF2,
184 0x7F, 0x35, 0xEC, 0xA9, 0x36, 0x77, 0xBE, 0xEC
186 digest = bytes(bytearray((
187 0x37, 0x54, 0xF3, 0xCF, 0xAC, 0xC9, 0xE0, 0x61,
188 0x5C, 0x4F, 0x4A, 0x7C, 0x4D, 0x8D, 0xAB, 0x53,
189 0x1B, 0x09, 0xB6, 0xF9, 0xC1, 0x70, 0xC5, 0x33,
190 0xA7, 0x1D, 0x14, 0x70, 0x35, 0xB0, 0xC5, 0x91,
191 0x71, 0x84, 0xEE, 0x53, 0x65, 0x93, 0xF4, 0x41,
192 0x43, 0x39, 0x97, 0x6C, 0x64, 0x7C, 0x5D, 0x5A,
193 0x40, 0x7A, 0xDE, 0xDB, 0x1D, 0x56, 0x0C, 0x4F,
194 0xC6, 0x77, 0x7D, 0x29, 0x72, 0x07, 0x5B, 0x8C
196 signature = bytes(bytearray((
197 0x2F, 0x86, 0xFA, 0x60, 0xA0, 0x81, 0x09, 0x1A,
198 0x23, 0xDD, 0x79, 0x5E, 0x1E, 0x3C, 0x68, 0x9E,
199 0xE5, 0x12, 0xA3, 0xC8, 0x2E, 0xE0, 0xDC, 0xC2,
200 0x64, 0x3C, 0x78, 0xEE, 0xA8, 0xFC, 0xAC, 0xD3,
201 0x54, 0x92, 0x55, 0x84, 0x86, 0xB2, 0x0F, 0x1C,
202 0x9E, 0xC1, 0x97, 0xC9, 0x06, 0x99, 0x85, 0x02,
203 0x60, 0xC9, 0x3B, 0xCB, 0xCD, 0x9C, 0x5C, 0x33,
204 0x17, 0xE1, 0x93, 0x44, 0xE1, 0x73, 0xAE, 0x36,
205 0x10, 0x81, 0xB3, 0x94, 0x69, 0x6F, 0xFE, 0x8E,
206 0x65, 0x85, 0xE7, 0xA9, 0x36, 0x2D, 0x26, 0xB6,
207 0x32, 0x5F, 0x56, 0x77, 0x8A, 0xAD, 0xBC, 0x08,
208 0x1C, 0x0B, 0xFB, 0xE9, 0x33, 0xD5, 0x2F, 0xF5,
209 0x82, 0x3C, 0xE2, 0x88, 0xE8, 0xC4, 0xF3, 0x62,
210 0x52, 0x60, 0x80, 0xDF, 0x7F, 0x70, 0xCE, 0x40,
211 0x6A, 0x6E, 0xEB, 0x1F, 0x56, 0x91, 0x9C, 0xB9,
212 0x2A, 0x98, 0x53, 0xBD, 0xE7, 0x3E, 0x5B, 0x4A
214 private_key = bytes2long(private_key)
215 signature = signature[64:] + signature[:64]
217 c = GOST3410Curve(p, q, a, b, x, y)
218 pubX, pubY = public_key(c, private_key)
219 self.assertEqual(long2bytes(pubX), public_key_x)
220 self.assertEqual(long2bytes(pubY), public_key_y)
221 s = sign(c, private_key, digest, size=SIZE_3410_2012)
222 self.assertTrue(verify(c, pubX, pubY, digest, s, size=SIZE_3410_2012))
223 self.assertTrue(verify(c, pubX, pubY, digest, signature, size=SIZE_3410_2012))
225 def test_sequence(self):
226 c = GOST3410Curve(*CURVE_PARAMS['GostR3410_2012_TC26_ParamSetA'])
227 private_key = bytes2long(urandom(64))
228 pubX, pubY = public_key(c, private_key)
231 s = sign(c, private_key, digest, size=SIZE_3410_2012)
232 self.assertTrue(verify(c, pubX, pubY, digest, s, size=SIZE_3410_2012))
233 self.assertNotIn(b'\x00' * 8, s)
236 class TestVKO(TestCase):
237 def test_sequence(self):
238 curve = GOST3410Curve(*CURVE_PARAMS['GostR3410_2001_TestParamSet'])
241 prv1 = bytes2long(urandom(32))
242 prv2 = bytes2long(urandom(32))
243 pub1 = public_key(curve, prv1)
244 pub2 = public_key(curve, prv2)
245 kek1 = kek(curve, prv1, ukm, pub2)
246 kek2 = kek(curve, prv2, ukm, pub1)
247 self.assertEqual(kek1, kek2)
248 kek1 = kek(curve, prv1, ukm, pub1)
249 kek2 = kek(curve, prv2, ukm, pub2)
250 self.assertNotEqual(kek1, kek2)