forked from RsaCtfTool/RsaCtfTool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wiener_attack.py
82 lines (71 loc) · 2.36 KB
/
wiener_attack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import sys
from sympy.solvers import solve
from sympy import Symbol
# A reimplementation of pablocelayes rsa-wiener-attack for this purpose
# https://github.com/pablocelayes/rsa-wiener-attack/
class WienerAttack(object):
def rational_to_contfrac(self, x, y):
a = x // y
if a * y == x:
return [a]
else:
pquotients = self.rational_to_contfrac(y, x - a * y)
pquotients.insert(0, a)
return pquotients
def convergents_from_contfrac(self, frac):
convs = []
for i in range(len(frac)):
convs.append(self.contfrac_to_rational(frac[0:i]))
return convs
def contfrac_to_rational(self, frac):
if len(frac) == 0:
return (0, 1)
elif len(frac) == 1:
return (frac[0], 1)
else:
remainder = frac[1:len(frac)]
(num, denom) = self.contfrac_to_rational(remainder)
return (frac[0] * num + denom, num)
def is_perfect_square(self, n):
h = n & 0xF
if h > 9:
return -1
if (h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8):
t = self.isqrt(n)
if t*t == n:
return t
else:
return -1
return -1
def isqrt(self, n):
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = 2**(a+b)
while True:
y = (x + n//x)//2
if y >= x:
return x
x = y
def __init__(self, n, e):
self.d = None
self.p = None
self.q = None
sys.setrecursionlimit(100000)
frac = self.rational_to_contfrac(e, n)
convergents = self.convergents_from_contfrac(frac)
for (k, d) in convergents:
if k != 0 and (e * d - 1) % k == 0:
phi = (e * d - 1) // k
s = n - phi + 1
discr = s*s - 4*n
if(discr >= 0):
t = self.is_perfect_square(discr)
if t != -1 and (s + t) % 2 == 0:
self.d = d
x = Symbol('x')
roots = solve(x**2 - s * x + n, x)
if len(roots) == 2:
self.p = roots[0]
self.q = roots[1]
break