This repository was archived by the owner on Mar 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 263
/
Copy pathpollardrho.py
130 lines (115 loc) · 3.59 KB
/
pollardrho.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
Source: Handbook of Applied Cryptography chapter-3
http://cacr.uwaterloo.ca/hac/about/chap3.pdf
"""
from Crypto.Util.number import *
def func_f(x_i, base, y, p):
"""
x_(i+1) = func_f(x_i)
"""
if x_i % 3 == 2:
return (y*x_i) % p
elif x_i % 3 == 0:
return pow(x_i, 2, p)
elif x_i % 3 == 1:
return base*x_i % p
else:
print "[-] Something's wrong!"
return -1
def func_g(a, n, p, x_i):
"""
a_(i+1) = func_g(a_i, x_i)
"""
if x_i % 3 == 2:
return a
elif x_i % 3 == 0:
return 2*a % n
elif x_i % 3 == 1:
return (a + 1) % n
else:
print "[-] Something's wrong!"
return -1
def func_h(b, n, p, x_i):
"""
b_(i+1) = func_g(b_i, x_i)
"""
if x_i % 3 == 2:
return (b + 1) % n
elif x_i % 3 == 0:
return 2*b % n
elif x_i % 3 == 1:
return b
else:
print "[-] Something's wrong!"
return -1
def pollardrho(base, y, p, n):
"""
Refer to section 3.6.3 of Handbook of Applied Cryptography
Computes `x` = a mod n for the DLP base**x % p == y
in the Group G = {0, 1, 2, ..., n}
given that order `n` is a prime number.
:parameters:
base : int/long
Generator of the group
y : int/long
Result of base**x % p
p : int/long
Group over which DLP is generated.
n : int/long
Order of the group generated by `base`.
Should be prime for this implementation
"""
if not isPrime(n):
print "[-] Order of group must be prime for Pollard Rho"
return -1
x_i = 1
x_2i = 1
a_i = 0
b_i = 0
a_2i = 0
b_2i = 0
i = 1
while i <= n:
# Single Step calculations
a_i = func_g(a_i, n, p, x_i)
b_i = func_h(b_i, n, p, x_i)
x_i = func_f(x_i, base, y, p)
# Double Step calculations
a_2i = func_g(func_g(a_2i, n, p, x_2i), n, p, func_f(x_2i, base, y, p))
b_2i = func_h(func_h(b_2i, n, p, x_2i), n, p, func_f(x_2i, base, y, p))
x_2i = func_f(func_f(x_2i, base, y, p), base, y, p)
if x_i == x_2i:
"""
If x_i == x_2i is True
==> (base^(a_i))*(y^(b_i)) = (base^(a_2i))*(y^(b_2i)) (mod p)
==> y^(b_i - b_2i) = base^(a_2i - a_i) (mod p)
==> base^((b_i - b_2i)*x) = base^(a_2i - a_i) (mod p)
==> (b_i - b_2i)*x = (a_2i - a_i) (mod n)
r = (b_i - b_2i) % n
if GCD(r, n) == 1 then,
==> x = (r^(-1))*(a_2i - a_i) (mod n)
"""
r = (b_i - b_2i) % n
if r == 0:
print "[-] b_i = b_2i, returning -1"
return -1
else:
assert GCD(r, n) == 1
"""
If `n` is not a prime number this algorithm will not be able to
solve the DLP, because GCD(r, n) != 1 then and one will have to
write an implementation to solve the equation:
(b_i - b_2i)*x = (a_2i - a_i) (mod n)
This equation will have multiple solutions out of which only one
will be the actual solution
"""
return (inverse(r, n)*(a_2i - a_i)) % n
else:
i += 1
continue
if __name__ == "__main__":
import random
for i in range(100):
num = random.randint(3, 381)
y = pow(2, num, 383)
assert pow(2, pollardrho(2, y, 383, 191), 383) == y