Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ashutosh1206
GitHub Repository: ashutosh1206/crypton
Path: blob/master/Discrete-Logarithm-Problem/Algo-Pollard-Rho/pollardrho.py
1402 views
1
"""
2
Source: Handbook of Applied Cryptography chapter-3
3
http://cacr.uwaterloo.ca/hac/about/chap3.pdf
4
"""
5
from Crypto.Util.number import *
6
7
def func_f(x_i, base, y, p):
8
"""
9
x_(i+1) = func_f(x_i)
10
"""
11
if x_i % 3 == 2:
12
return (y*x_i) % p
13
elif x_i % 3 == 0:
14
return pow(x_i, 2, p)
15
elif x_i % 3 == 1:
16
return base*x_i % p
17
else:
18
print "[-] Something's wrong!"
19
return -1
20
21
def func_g(a, n, p, x_i):
22
"""
23
a_(i+1) = func_g(a_i, x_i)
24
"""
25
if x_i % 3 == 2:
26
return a
27
elif x_i % 3 == 0:
28
return 2*a % n
29
elif x_i % 3 == 1:
30
return (a + 1) % n
31
else:
32
print "[-] Something's wrong!"
33
return -1
34
35
def func_h(b, n, p, x_i):
36
"""
37
b_(i+1) = func_g(b_i, x_i)
38
"""
39
if x_i % 3 == 2:
40
return (b + 1) % n
41
elif x_i % 3 == 0:
42
return 2*b % n
43
elif x_i % 3 == 1:
44
return b
45
else:
46
print "[-] Something's wrong!"
47
return -1
48
49
def pollardrho(base, y, p, n):
50
"""
51
Refer to section 3.6.3 of Handbook of Applied Cryptography
52
53
Computes `x` = a mod n for the DLP base**x % p == y
54
in the Group G = {0, 1, 2, ..., n}
55
given that order `n` is a prime number.
56
57
:parameters:
58
base : int/long
59
Generator of the group
60
y : int/long
61
Result of base**x % p
62
p : int/long
63
Group over which DLP is generated.
64
n : int/long
65
Order of the group generated by `base`.
66
Should be prime for this implementation
67
"""
68
69
if not isPrime(n):
70
print "[-] Order of group must be prime for Pollard Rho"
71
return -1
72
73
x_i = 1
74
x_2i = 1
75
76
a_i = 0
77
b_i = 0
78
a_2i = 0
79
b_2i = 0
80
81
i = 1
82
while i <= n:
83
# Single Step calculations
84
a_i = func_g(a_i, n, p, x_i)
85
b_i = func_h(b_i, n, p, x_i)
86
x_i = func_f(x_i, base, y, p)
87
88
# Double Step calculations
89
a_2i = func_g(func_g(a_2i, n, p, x_2i), n, p, func_f(x_2i, base, y, p))
90
b_2i = func_h(func_h(b_2i, n, p, x_2i), n, p, func_f(x_2i, base, y, p))
91
x_2i = func_f(func_f(x_2i, base, y, p), base, y, p)
92
93
if x_i == x_2i:
94
"""
95
If x_i == x_2i is True
96
==> (base^(a_i))*(y^(b_i)) = (base^(a_2i))*(y^(b_2i)) (mod p)
97
==> y^(b_i - b_2i) = base^(a_2i - a_i) (mod p)
98
==> base^((b_i - b_2i)*x) = base^(a_2i - a_i) (mod p)
99
==> (b_i - b_2i)*x = (a_2i - a_i) (mod n)
100
101
r = (b_i - b_2i) % n
102
if GCD(r, n) == 1 then,
103
==> x = (r^(-1))*(a_2i - a_i) (mod n)
104
105
"""
106
r = (b_i - b_2i) % n
107
if r == 0:
108
print "[-] b_i = b_2i, returning -1"
109
return -1
110
else:
111
assert GCD(r, n) == 1
112
"""
113
If `n` is not a prime number this algorithm will not be able to
114
solve the DLP, because GCD(r, n) != 1 then and one will have to
115
write an implementation to solve the equation:
116
(b_i - b_2i)*x = (a_2i - a_i) (mod n)
117
This equation will have multiple solutions out of which only one
118
will be the actual solution
119
"""
120
return (inverse(r, n)*(a_2i - a_i)) % n
121
else:
122
i += 1
123
continue
124
125
if __name__ == "__main__":
126
import random
127
for i in range(100):
128
num = random.randint(3, 381)
129
y = pow(2, num, 383)
130
assert pow(2, pollardrho(2, y, 383, 191), 383) == y
131
132