Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/test/test_ecc.py
2587 views
1
import os
2
import sys
3
from random import getrandbits
4
from random import randrange
5
from unittest import TestCase
6
7
from sage.all import EllipticCurve
8
from sage.all import GF
9
10
path = os.path.dirname(os.path.dirname(os.path.realpath(os.path.abspath(__file__))))
11
if sys.path[1] != path:
12
sys.path.insert(1, path)
13
14
from attacks.ecc import ecdsa_nonce_reuse
15
from attacks.ecc import frey_ruck_attack
16
from attacks.ecc import mov_attack
17
from attacks.ecc import parameter_recovery
18
from attacks.ecc import singular_curve
19
from attacks.ecc import smart_attack
20
21
22
class TestECC(TestCase):
23
_O = "origin"
24
25
def _negation(self, p, P):
26
if P == self._O:
27
return P
28
29
return P[0], -P[1] % p
30
31
def _add(self, p, a2, a4, P1, P2):
32
if P1 == self._O:
33
return P2
34
35
if P2 == self._O:
36
return P1
37
38
if P1 == self._negation(p, P2):
39
return self._O
40
41
if P1 == P2:
42
gradient = (3 * P1[0] ** 2 + 2 * a2 * P1[0] + a4) * pow(2 * P1[1], -1, p) % p
43
else:
44
gradient = (P2[1] - P1[1]) * pow(P2[0] - P1[0], -1, p) % p
45
46
x = (gradient ** 2 - a2 - P1[0] - P2[0]) % p
47
y = (gradient * (P1[0] - x) - P1[1]) % p
48
return x, y
49
50
def _double_and_add(self, p, a2, a4, G, l):
51
multiplication_result = self._O
52
double = G
53
while l > 0:
54
if l % 2 == 1:
55
multiplication_result = self._add(p, a2, a4, multiplication_result, double)
56
57
double = self._add(p, a2, a4, double, double)
58
l //= 2
59
60
return multiplication_result
61
62
def test_ecdsa_nonce_reuse(self):
63
p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
64
a = 115792089210356248762697446949407573530086143415290314195533631308867097853948
65
b = 41058363725152142129326129780047268409114441015993725554835256314039467401291
66
p_256 = EllipticCurve(GF(p), [a, b])
67
G = p_256.gen(0)
68
n = int(G.order())
69
x = randrange(1, n)
70
k = randrange(1, n)
71
r = int((k * G).xy()[0])
72
m1 = getrandbits(n.bit_length())
73
s1 = pow(k, -1, n) * (m1 + r * x) % n
74
m2 = getrandbits(n.bit_length())
75
s2 = pow(k, -1, n) * (m2 + r * x) % n
76
for k_, x_ in ecdsa_nonce_reuse.attack(n, m1, r, s1, m2, r, s2):
77
self.assertIsInstance(k_, int)
78
self.assertIsInstance(x_, int)
79
if k_ == k and x_ == x:
80
break
81
else:
82
self.fail()
83
84
def test_frey_ruck_attack(self):
85
p = 23305425500899
86
a = 13079575536215
87
b = 951241857177
88
l = 709658
89
E = EllipticCurve(GF(p), [a, b])
90
P = E(17662927853004, 1766549410280)
91
R = E(2072411881257, 5560421985272)
92
l_ = frey_ruck_attack.attack(P, R)
93
self.assertIsInstance(l_, int)
94
self.assertEqual(l, l_)
95
96
p = 93340306032025588917032364977153
97
a = 71235469403697021051902688366816
98
b = 47490312935798014034601792244544
99
l = 764009
100
E = EllipticCurve(GF(p), [a, b])
101
P = E(10362409929965041614317835692463, 79529049191468905652172306035573)
102
R = E(15411349585423321468944221089888, 9416052907883278088782335830033)
103
l_ = frey_ruck_attack.attack(P, R)
104
self.assertIsInstance(l_, int)
105
self.assertEqual(l, l_)
106
107
p = 23305425500899
108
a = 1
109
b = 0
110
l = 4500974
111
E = EllipticCurve(GF(p), [a, b])
112
P = E(18414716422748, 9607997424906)
113
R = E(22829488331658, 15463570264423)
114
l_ = frey_ruck_attack.attack(P, R)
115
self.assertIsInstance(l_, int)
116
self.assertEqual(l, l_)
117
118
p = 625276251724681468065787127391468008213949163
119
a = 625276251724681468065787127391468008213949162
120
b = 0
121
l = 573267844
122
E = EllipticCurve(GF(p), [a, b])
123
P = E(106475251480616516532312035568555890205578047, 431897649280430503785680130194791468278435206)
124
R = E(325210632278386769754263691768220745652895158, 308687159471094662490925278095484225164835682)
125
l_ = frey_ruck_attack.attack(P, R)
126
self.assertIsInstance(l_, int)
127
self.assertEqual(l, l_)
128
129
p = 1527181879
130
a = 623779536
131
b = 170102
132
l = 16029094
133
E = EllipticCurve(GF(p), [a, b])
134
P = E(470008538, 130171157)
135
R = E(1247215477, 775699526)
136
l_ = frey_ruck_attack.attack(P, R)
137
self.assertIsInstance(l_, int)
138
self.assertEqual(l, l_)
139
140
def test_mov_attack(self):
141
p = 23305425500899
142
a = 13079575536215
143
b = 951241857177
144
l = 709658
145
E = EllipticCurve(GF(p), [a, b])
146
P = E(17662927853004, 1766549410280)
147
R = E(2072411881257, 5560421985272)
148
l_ = mov_attack.attack(P, R)
149
self.assertIsInstance(l_, int)
150
self.assertEqual(l, l_)
151
152
p = 93340306032025588917032364977153
153
a = 71235469403697021051902688366816
154
b = 47490312935798014034601792244544
155
l = 764009
156
E = EllipticCurve(GF(p), [a, b])
157
P = E(10362409929965041614317835692463, 79529049191468905652172306035573)
158
R = E(15411349585423321468944221089888, 9416052907883278088782335830033)
159
l_ = mov_attack.attack(P, R)
160
self.assertIsInstance(l_, int)
161
self.assertEqual(l, l_)
162
163
p = 23305425500899
164
a = 1
165
b = 0
166
l = 4500974
167
E = EllipticCurve(GF(p), [a, b])
168
P = E(18414716422748, 9607997424906)
169
R = E(22829488331658, 15463570264423)
170
l_ = mov_attack.attack(P, R)
171
self.assertIsInstance(l_, int)
172
self.assertEqual(l, l_)
173
174
p = 625276251724681468065787127391468008213949163
175
a = 625276251724681468065787127391468008213949162
176
b = 0
177
l = 573267844
178
E = EllipticCurve(GF(p), [a, b])
179
P = E(106475251480616516532312035568555890205578047, 431897649280430503785680130194791468278435206)
180
R = E(325210632278386769754263691768220745652895158, 308687159471094662490925278095484225164835682)
181
l_ = mov_attack.attack(P, R)
182
self.assertIsInstance(l_, int)
183
self.assertEqual(l, l_)
184
185
p = 1527181879
186
a = 623779536
187
b = 170102
188
l = 16029094
189
E = EllipticCurve(GF(p), [a, b])
190
P = E(470008538, 130171157)
191
R = E(1247215477, 775699526)
192
l_ = mov_attack.attack(P, R)
193
self.assertIsNone(l_)
194
195
def test_parameter_recovery(self):
196
p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
197
a = 115792089210356248762697446949407573530086143415290314195533631308867097853948
198
b = 41058363725152142129326129780047268409114441015993725554835256314039467401291
199
p_256 = EllipticCurve(GF(p), [a, b])
200
x1, y1 = p_256.random_point().xy()
201
x2, y2 = p_256.random_point().xy()
202
a_, b_ = parameter_recovery.attack(p, x1, y1, x2, y2)
203
self.assertIsInstance(a_, int)
204
self.assertIsInstance(b_, int)
205
self.assertEqual(a, a_)
206
self.assertEqual(b, b_)
207
208
def test_singular_curve(self):
209
# Singular point is a cusp.
210
p = 29800669538070463271
211
a2 = 9813480773723366080
212
a4 = 13586186857864981308
213
a6 = 18910877985247806581
214
Gx = 13284247619583658910
215
Gy = 3629049282720081919
216
# We don't know the order of the base point, so we keep l pretty low to make sure we don't exceed it.
217
l = randrange(1, 4096)
218
Px, Py = self._double_and_add(p, a2, a4, (Gx, Gy), l)
219
l_ = singular_curve.attack(p, a2, a4, a6, Gx, Gy, Px, Py)
220
self.assertIsInstance(l_, int)
221
self.assertEqual(l, l_)
222
223
# Singular point is a node.
224
p = 29800669538070463271
225
a2 = 13753215131529770662
226
a4 = 16713139382466325228
227
a6 = 19476075514740408653
228
Gx = 16369123140759309684
229
Gy = 5098114980663762719
230
# We don't know the order of the base point, so we keep l pretty low to make sure we don't exceed it.
231
l = randrange(1, 4096)
232
Px, Py = self._double_and_add(p, a2, a4, (Gx, Gy), l)
233
l_ = singular_curve.attack(p, a2, a4, a6, Gx, Gy, Px, Py)
234
self.assertIsInstance(l_, int)
235
self.assertEqual(l, l_)
236
237
def test_smart_attack(self):
238
F = GF(23304725718649417969)
239
E = EllipticCurve(F, [8820341459377516260, 5880227639585010840])
240
G = E.gen(0)
241
l = randrange(1, G.order())
242
l_ = smart_attack.attack(G, l * G)
243
self.assertIsInstance(l_, int)
244
self.assertEqual(l, l_)
245
246
F = GF(11 ** 2)
247
g = F.gen()
248
E = EllipticCurve(F, [g, 8 * g])
249
G = E.gen(0)
250
for l in range(1, G.order()):
251
l_ = smart_attack.attack(G, l * G)
252
self.assertIsInstance(l_, int)
253
self.assertEqual(l, l_)
254
255
F = GF(13 ** 3)
256
g = F.gen()
257
E = EllipticCurve(F, [g ** 2, g ** 2 + 9 * g + 8])
258
G = E.gen(0)
259
for l in range(1, G.order()):
260
l_ = smart_attack.attack(G, l * G)
261
262
F = GF(17 ** 4)
263
g = F.gen()
264
E = EllipticCurve(F, [13 * g ** 3 + 5 * g ** 2 + 12 * g + 9, g ** 3 + g ** 2 + 9 * g + 11])
265
G = E.gen(0)
266
l = randrange(1, G.order())
267
l_ = smart_attack.attack(G, l * G)
268
self.assertIsInstance(l_, int)
269
self.assertEqual(l, l_)
270
271