2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2019 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/>.
17 """ GOST R 34.10 public-key signature function.
19 This is implementation of GOST R 34.10-2001 (:rfc:`5832`), GOST R
20 34.10-2012 (:rfc:`7091`). The difference between 2001 and 2012 is the
21 key, digest and signature lengths.
24 from os import urandom
26 from pygost.utils import bytes2long
27 from pygost.utils import hexdec
28 from pygost.utils import long2bytes
29 from pygost.utils import modinvert
38 class GOST3410Curve(object):
39 """ GOST 34.10 validated curve
41 >>> curve = CURVES["id-GostR3410-2001-TestParamSet"]
42 >>> prv = prv_unmarshal(urandom(32))
43 >>> signature = sign(curve, prv, GOST341194(data).digest())
44 >>> pub = public_key(curve, prv)
45 >>> verify(curve, pub, GOST341194(data).digest(), signature)
48 def __init__(self, p, q, a, b, x, y):
55 r1 = self.y * self.y % self.p
56 r2 = ((self.x * self.x + self.a) * self.x + self.b) % self.p
60 raise ValueError("Invalid parameters")
67 def _add(self, p1x, p1y, p2x, p2y):
68 if p1x == p2x and p1y == p2y:
70 t = ((3 * p1x * p1x + self.a) * modinvert(2 * p1y, self.p)) % self.p
72 tx = self._pos(p2x - p1x) % self.p
73 ty = self._pos(p2y - p1y) % self.p
74 t = (ty * modinvert(tx, self.p)) % self.p
75 tx = self._pos(t * t - p1x - p2x) % self.p
76 ty = self._pos(t * (p1x - tx) - p1y) % self.p
79 def exp(self, degree, x=None, y=None):
85 raise ValueError("Bad degree value")
89 tx, ty = self._add(tx, ty, x, y)
91 x, y = self._add(x, y, x, y)
96 "GostR3410_2001_ParamSet_cc": GOST3410Curve(
97 p=bytes2long(hexdec("C0000000000000000000000000000000000000000000000000000000000003C7")),
98 q=bytes2long(hexdec("5fffffffffffffffffffffffffffffff606117a2f4bde428b7458a54b6e87b85")),
99 a=bytes2long(hexdec("C0000000000000000000000000000000000000000000000000000000000003c4")),
100 b=bytes2long(hexdec("2d06B4265ebc749ff7d0f1f1f88232e81632e9088fd44b7787d5e407e955080c")),
101 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")),
102 y=bytes2long(hexdec("a20e034bf8813ef5c18d01105e726a17eb248b264ae9706f440bedc8ccb6b22c")),
104 "id-GostR3410-2001-TestParamSet": GOST3410Curve(
105 p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000431")),
106 q=bytes2long(hexdec("8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B3")),
107 a=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000007")),
108 b=bytes2long(hexdec("5FBFF498AA938CE739B8E022FBAFEF40563F6E6A3472FC2A514C0CE9DAE23B7E")),
109 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")),
110 y=bytes2long(hexdec("08E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8")),
112 "id-GostR3410-2001-CryptoPro-A-ParamSet": GOST3410Curve(
113 p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")),
114 q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893")),
115 a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94")),
116 b=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000a6")),
117 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")),
118 y=bytes2long(hexdec("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14")),
120 "id-GostR3410-2001-CryptoPro-B-ParamSet": GOST3410Curve(
121 p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C99")),
122 q=bytes2long(hexdec("800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F")),
123 a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C96")),
124 b=bytes2long(hexdec("3E1AF419A269A5F866A7D3C25C3DF80AE979259373FF2B182F49D4CE7E1BBC8B")),
125 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")),
126 y=bytes2long(hexdec("3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC")),
128 "id-GostR3410-2001-CryptoPro-C-ParamSet": GOST3410Curve(
129 p=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B")),
130 q=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9")),
131 a=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598")),
132 b=bytes2long(hexdec("000000000000000000000000000000000000000000000000000000000000805a")),
133 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000000")),
134 y=bytes2long(hexdec("41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67")),
136 "id-GostR3410-2001-CryptoPro-XchA-ParamSet": GOST3410Curve(
137 p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")),
138 q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893")),
139 a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94")),
140 b=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000a6")),
141 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")),
142 y=bytes2long(hexdec("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14")),
144 "id-GostR3410-2001-CryptoPro-XchB-ParamSet": GOST3410Curve(
145 p=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B")),
146 q=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9")),
147 a=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598")),
148 b=bytes2long(hexdec("000000000000000000000000000000000000000000000000000000000000805a")),
149 x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000000")),
150 y=bytes2long(hexdec("41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67")),
152 "id-tc26-gost-3410-2012-256-paramSetA": GOST3410Curve(
153 p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")),
154 q=bytes2long(hexdec("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67")),
155 a=bytes2long(hexdec("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335")),
156 b=bytes2long(hexdec("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513")),
157 x=bytes2long(hexdec("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28")),
158 y=bytes2long(hexdec("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C")),
160 "id-tc26-gost-3410-12-512-paramSetA": GOST3410Curve(
161 p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")),
162 q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275")),
163 a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4")),
164 b=bytes2long(hexdec("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760")),
165 x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")),
166 y=bytes2long(hexdec("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4")),
168 "id-tc26-gost-3410-12-512-paramSetB": GOST3410Curve(
169 p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F")),
170 q=bytes2long(hexdec("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD")),
171 a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C")),
172 b=bytes2long(hexdec("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116")),
173 x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")),
174 y=bytes2long(hexdec("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD")),
176 "id-tc26-gost-3410-2012-512-paramSetC": GOST3410Curve(
177 p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")),
178 q=bytes2long(hexdec("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED")),
179 a=bytes2long(hexdec("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3")),
180 b=bytes2long(hexdec("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1")),
181 x=bytes2long(hexdec("E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148")),
182 y=bytes2long(hexdec("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F")),
185 DEFAULT_CURVE = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"]
188 def public_key(curve, prv):
189 """ Generate public key from the private one
191 :param GOST3410Curve curve: curve to use
192 :param long prv: private key
193 :returns: public key's parts, X and Y
196 return curve.exp(prv)
199 def sign(curve, prv, digest, mode=2001):
200 """ Calculate signature for provided digest
202 :param GOST3410Curve curve: curve to use
203 :param long prv: private key
204 :param digest: digest for signing
205 :type digest: bytes, 32 or 64 bytes
207 :rtype: bytes, 64 or 128 bytes
209 size = MODE2SIZE[mode]
211 e = bytes2long(digest) % q
215 k = bytes2long(urandom(size)) % q
228 return long2bytes(s, size) + long2bytes(r, size)
231 def verify(curve, pub, digest, signature, mode=2001):
232 """ Verify provided digest with the signature
234 :param GOST3410Curve curve: curve to use
235 :type pub: (long, long)
236 :param digest: digest needed to check
237 :type digest: bytes, 32 or 64 bytes
238 :param signature: signature to verify with
239 :type signature: bytes, 64 or 128 bytes
242 size = MODE2SIZE[mode]
243 if len(signature) != size * 2:
244 raise ValueError("Invalid signature length")
247 s = bytes2long(signature[:size])
248 r = bytes2long(signature[size:])
249 if r <= 0 or r >= q or s <= 0 or s >= q:
251 e = bytes2long(digest) % curve.q
257 p1x, p1y = curve.exp(z1)
258 q1x, q1y = curve.exp(z2, pub[0], pub[1])
262 lm = modinvert(lm, p)
271 # This is not constant time comparison!
275 def prv_unmarshal(prv):
276 """Unmarshal private key
278 :param bytes prv: serialized private key
281 return bytes2long(prv[::-1])
284 def pub_marshal(pub, mode=2001):
285 """Marshal public key
287 :type pub: (long, long)
290 size = MODE2SIZE[mode]
291 return (long2bytes(pub[1], size) + long2bytes(pub[0], size))[::-1]
294 def pub_unmarshal(pub, mode=2001):
295 """Unmarshal public key
300 size = MODE2SIZE[mode]
302 return (bytes2long(pub[size:]), bytes2long(pub[:size]))