Skip to content

Commit

Permalink
Pollard algorithm now traverses the entire divisor group modulo n, wh…
Browse files Browse the repository at this point in the history
…ich will lead to the correct result in all cases, new demo in readme
  • Loading branch information
ZeroBone committed Jul 27, 2020
1 parent 7c8cb6e commit ab9772a
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 30 deletions.
64 changes: 55 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,79 @@
This is my implementation of RSA cracking algorithm based on Pollard factorization. It will work if the prime number `n` as part of the public key has not a very big maximum prime factor. Of course, all modern RSA implementations don't have this security hole so this is more of an educational project that doesn't have much real-world applications.

# Usage
In order to start the script, simply run `python pollard.py`
In order to start the script, simply run `python cracker.py`

You will need 4 inputs:
1. `b` - the maximum prime factor of `n`.
2. `n` - prime number in the public key so that `m = c ^ d mod n` where `m` is the message, `c` is the encrypted message, `d` is the private key.
1. `n` - prime number in the public key so that `m = c ^ d mod n` where `m` is the message, `c` is the encrypted message, `d` is the private key.
2. `e` - the second public key component (so that `gcd(e, phi(n)) = 1`).
3. `c` - the encrypted message.
4. `e` - the second public key component (so that `gcd(e, phi(n)) = 1`).
4. `b` - the maximum prime factor of `n`. This field is optional. However, if you leave it blank, the brute-force algorithm will be used for factorizing `n`.

# Demo
```
Enter b (the maximum prime number factor): 200000
Enter n (as part of the public key): 186444745729857899758373984272541398503249351266417000699738642133172271283265124803102459
Enter c (the encrypted message to decrypt): 159178142916077677757648147687519523540045276157456113470673097514775229976995968698190914
Enter e (as part of the public key): 65537
Factorizing n to find its prime divisors...
Enter c (the encrypted message to decrypt): 159178142916077677757648147687519523540045276157456113470673097514775229976995968698190914
Enter b (the maximum prime factor in n, optional): 200000
Factorizing n with the Pollard algorithm...
k has 86871 digits
Trying to solve with a = 2
(a ^ k mod n) - 1 = 95072790833932492612013226959843266212858324985456485206430737027466196168851937286400160
p = 2962244945158622279601750283735698362054297
q = 62940354083336669282335053470277744418281466547
Factorizing complete.
phi(n) = 186444745729857899758373984272541398503249288323100672417910737518517050721785008159581616
Solving e * d = 1 mod phi(n) with the euklidian algorithm...
a = -41924961744066952541910026492278294547238731739590378098215520069737488388039514552813743
b = 14737
d (private key) = 144519783985790947216463957780263103956010556583510294319695217448779562333745493606767873
m (decrypted message) = 2020
```

# Demo with small numbers
## Brute-force
```
Enter n (as part of the public key): 493
Enter e (as part of the public key): 45
Enter c (the encrypted message to decrypt): 56
Enter b (the maximum prime factor in n, optional):
Factorizing n with the BRUTEFORCE algorithm...
p = 17
q = 29
Factorizing complete.
phi(n) = 448
Solving e * d = 1 mod phi(n) with the euklidian algorithm...
d (private key) = 229
m (decrypted message) = 490
```
## Pollard
```
Enter n (as part of the public key): 493
Enter e (as part of the public key): 45
Enter c (the encrypted message to decrypt): 56
Enter b (the maximum prime factor in n, optional): 493
Factorizing n with the Pollard algorithm...
k has 216 digits
Trying to solve with a = 2
(a ^ k mod n) - 1 = 0
Trying to solve with a = 3
(a ^ k mod n) - 1 = 0
Trying to solve with a = 4
(a ^ k mod n) - 1 = 0
...
Trying to solve with a = 509
(a ^ k mod n) - 1 = 0
Trying to solve with a = 510
(a ^ k mod n) - 1 = 203
p = 29
q = 17
Factorizing complete.
phi(n) = 448
Solving e * d = 1 mod phi(n) with the euklidian algorithm...
d (private key) = 229
m (decrypted message) = 490
```

# Credits
* Mirko Hoehn for helping me with the mathematics behind RSA.

Expand Down
6 changes: 4 additions & 2 deletions cracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
n = int(input("Enter n (as part of the public key): "))
e = int(input("Enter e (as part of the public key): "))
c = int(input("Enter c (the encrypted message to decrypt): "))
b = int(input("Enter b (the maximum prime factor in n, optional): ") or n)
b = int(input("Enter b (the maximum prime factor in n, optional): ") or 1)

# Demo:
# n = 186444745729857899758373984272541398503249351266417000699738642133172271283265124803102459
Expand All @@ -24,11 +24,13 @@

p = None

if b >= n or b < 1:
if b > n or b <= 1:
print("Factorizing n with the BRUTEFORCE algorithm...")
p = find_factor(n)
else:
print("Factorizing n with the Pollard algorithm...")
if b > n - 1:
b = n - 1
p = pollard(b, n)

print("p = " + str(p))
Expand Down
10 changes: 8 additions & 2 deletions euklidian.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,11 @@ def inverse_modulo(a, n):

if b < 0:
b += n

return b

return b

def next_divisor_of(d, n):
d = d + 1
while d < n and gcd(d, n) != 1:
d = d + 1
return d
31 changes: 14 additions & 17 deletions pollard.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from prime import nextPrime
from powmod import aPowbModn
from euklidian import gcd
from euklidian import gcd, next_divisor_of

def calculateK(b):

Expand All @@ -28,7 +28,7 @@ def calculateK(b):
maximalePrimFaktor = currentPrimFaktor
currentExponent += 1

print("Found factor in k: "+str(currentPrime)+" ^ "+str(currentExponent)+" = "+str(maximalePrimFaktor))
# print("Found factor in k: "+str(currentPrime)+" ^ "+str(currentExponent)+" = "+str(maximalePrimFaktor))

k *= maximalePrimFaktor

Expand All @@ -40,25 +40,22 @@ def pollard(b, n):

k = calculateK(b)

factor = 1

while n % 2 == 0:
factor = factor * 2
n = n // 2
# print("k = " + str(k))
print("k has " + str(len(str(k))) + " digits")

p = 1
# a is an arbitraty element in the multiplicative group of divisors of 1 modulo n
# as gcd(n-1, n) = 1 for all n, we can pick a = n - 1
# or we can pick 2 if n is odd
a = 2 # n - 1
a = next_divisor_of(1, n)

# print("k = " + str(k))
print("k has " + str(len(str(k))) + " digits")
print("a = " + str(a))
while p == 1 or p >= n:
print("Trying to solve with a = " + str(a))

aPowKModNminus1 = aPowbModn(a, k, n) - 1

aPowKModNminus1 = aPowbModn(a, k, n) - 1
print("(a ^ k mod n) - 1 = " + str(aPowKModNminus1))

print("(a ^ k mod n) - 1 = " + str(aPowKModNminus1))
p = gcd(aPowKModNminus1, n)

p = gcd(aPowKModNminus1, n)
a = next_divisor_of(a, n)

return factor * p
return p

0 comments on commit ab9772a

Please sign in to comment.