This repository has been archived by the owner on Mar 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 258
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dd28d42
commit 385b72b
Showing
43 changed files
with
1,257 additions
and
10 deletions.
There are no files selected for viewing
Binary file added
BIN
+370 Bytes
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/Pictures/1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+299 Bytes
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/Pictures/2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+354 Bytes
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/Pictures/3.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+668 Bytes
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/Pictures/5.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+391 Bytes
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/Pictures/6.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+558 Bytes
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/Pictures/7.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions
55
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Baby Step Giant Step Algorithm | ||
|
||
**Prerequisites**: | ||
1. [Cyclic Groups](https://github.com/ashutosh1206/Crypton/blob/master/Discrete-Logarithm-Problem/README.md#cyclic-groups) | ||
2. [Discrete Logarithm Problem](https://github.com/ashutosh1206/Crypton/blob/master/Discrete-Logarithm-Problem/README.md) | ||
|
||
A method to reduce the time complexity of solving DLP is to use **Baby Step Giant Step Algorithm**. While brute forcing DLP takes polynomial time of the order ![picture](Pictures/2.gif), Baby Step Giant Step Algorithm can compute the value of `x` in ![picture](Pictures/1.gif) polynomial time complexity. Here, `n` is the order of the group. | ||
|
||
This algorithm is a tradeoff between time and space complexity, as we will see when we discuss the algorithm. | ||
|
||
## Algorithm | ||
`x` can be expressed as **x = i*m + j**, where ![picture](Pictures/3.gif) and `0 <= i,j < m`. | ||
|
||
Hence, we have: | ||
![picture](Pictures/4.gif) | ||
![picture](Pictures/5.gif) | ||
|
||
We can now use the above property for solving DLP as follows: | ||
1. Iterate `j` in its range and store all values of ![picture](Pictures/6.gif) with corresponding values of `j` in a lookup table. | ||
2. Run through each possible iteration of `i` and check if ![picture](Pictures/7.gif) exists in the table (ie. check if ![picture](Pictures/7.gif) == ![picture](Pictures/6.gif)). | ||
+ If it does then return **i*m + j** as the value of `x` | ||
+ Else, continue | ||
|
||
## Shortcomings | ||
Although the algorithm is more efficient as compared to plain brute-forcing, other algorithms of the same time complexity (Pollard's rho) are used for solving DLPs because of the fact that storing the look up table requires quite a lot of space. | ||
|
||
## Implementation | ||
I wrote an implementation of the above algorithm in python/sage: | ||
|
||
```python | ||
from sage.all import * | ||
|
||
def bsgs(g, y, p): | ||
mod_size = len(bin(p-1)[2:]) | ||
|
||
print "[+] Using BSGS algorithm to solve DLP" | ||
print "[+] Modulus size: " + str(mod_size) + ". Warning! BSGS not space efficient\n" | ||
|
||
m = ceil(sqrt(p-1)) | ||
# Baby Step | ||
lookup_table = {pow(g, j, p): j for j in range(m)} | ||
# Giant Step pre-computation | ||
c = pow(g, m*(p-2), p) | ||
# Giant Steps | ||
for i in range(m): | ||
temp = (y*pow(c, i, p)) % p | ||
if temp in lookup_table: | ||
# x found | ||
return i*m + lookup_table[temp] | ||
return None | ||
``` | ||
You can check out the complete code here: [bsgs.py](bsgs.py) | ||
|
||
## Resources & References | ||
1. [Rahul Sridhar- Survey of Discrete Log Algorithms](https://fortenf.org/e/crypto/2017/12/03/survey-of-discrete-log-algos.html) |
54 changes: 54 additions & 0 deletions
54
Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/bsgs.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from sage.all import * | ||
|
||
def bsgs(g, y, p): | ||
""" | ||
Reference: | ||
To solve DLP: y = g^x % p and get the value of x. | ||
We use the property that x = i*m + j, where m = ceil(sqrt(n)) | ||
:parameters: | ||
g : int/long | ||
Generator of the group | ||
y : int/long | ||
Result of g**x % p | ||
p : int/long | ||
Group over which DLP is generated. Commonly p is a prime number | ||
:variables: | ||
m : int/long | ||
Upper limit of baby steps / giant steps | ||
x_poss : int/long | ||
Values calculated in each giant step | ||
c : int/long | ||
Giant Step pre-computation: c = g^(-m) % p | ||
i, j : int/long | ||
Giant Step, Baby Step variables | ||
lookup_table: dictionary | ||
Dictionary storing all the values computed in the baby step | ||
""" | ||
mod_size = len(bin(p-1)[2:]) | ||
|
||
print "[+] Using BSGS algorithm to solve DLP" | ||
print "[+] Modulus size: " + str(mod_size) + ". Warning! BSGS not space efficient\n" | ||
|
||
m = ceil(sqrt(p-1)) | ||
# Baby Step | ||
lookup_table = {pow(g, j, p): j for j in range(m)} | ||
# Giant Step pre-computation | ||
c = pow(g, m*(p-2), p) | ||
# Giant Steps | ||
for i in range(m): | ||
temp = (y*pow(c, i, p)) % p | ||
if temp in lookup_table: | ||
# x found | ||
return i*m + lookup_table[temp] | ||
return None | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
assert pow(2, bsgs(2, 4178319614, 6971096459), 6971096459) == 4178319614 | ||
assert pow(3, bsgs(3, 362073897, 2500000001), 2500000001) == 362073897 | ||
except: | ||
print "[+] Function inconsistent and incorrect, check the implementation" |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Pohlig Hellman Algorithm | ||
|
||
**Prerequisites**: | ||
1. [Discrete Logarithm Problem](https://github.com/ashutosh1206/Crypton/tree/master/Discrete-Logarithm-Problem) | ||
|
||
**Pohlig Hellman Algorithm** is applicable in cases where order of the group, over which DLP is defined, is a smooth number (ie. the number that can be factored into small prime numbers). First, let us define our DLP over the Cyclic Group `G` = ![picture](Pictures/1.gif) having order `n`. | ||
|
||
There are different variations to Pohlig-Hellman algorithm that can be applied in different conditions: | ||
1. When **order** of a group **is a power of 2 only** ie. n = 2<sup>e</sup> | ||
2. When **order** of a group **is a power of a prime** ie. n = p<sup>e</sup>, where `p` is a prime number | ||
3. **General algorithm** ie. n = p<sub>1</sub><sup>e<sub>1</sub></sup> p<sub>2</sub><sup>e<sub>2</sub></sup> p<sub>3</sub><sup>e<sub>3</sub></sup>... p<sub>r</sub><sup>e<sub>r</sub></sup> | ||
|
||
## Order of a group is a power of 2 | ||
![picture](Pictures/2.png) | ||
*Source: https://crypto.stackexchange.com/questions/34180/discrete-logarithm-problem-is-easy-in-a-cyclic-group-of-order-a-power-of-two* | ||
|
||
I implemented this algorithm in python here: [ph_orderp2.py](ph_orderp2.py) | ||
|
||
So if you have a group whose order is a power of 2, you can now solve the DLP in ![picture](Pictures/2.gif), where `e` is the exponent in the group order n = 2<sup>e</sup>. | ||
|
||
## Order of a group is a power of a prime number | ||
|
||
**Source**: [http://anh.cs.luc.edu/331/notes/PohligHellmanp_k2p.pdf](http://anh.cs.luc.edu/331/notes/PohligHellmanp_k2p.pdf) | ||
|
||
I implemented this algorithm in python here: [ph_orderpp.py](ph_orderpp.py) | ||
|
||
## General Algorithm | ||
|
||
**Source**: [http://anh.cs.luc.edu/331/notes/PohligHellmanp_k2p.pdf](http://anh.cs.luc.edu/331/notes/PohligHellmanp_k2p.pdf) | ||
|
||
I implemented this algorithm in python/sage here: | ||
[pohlig_hellman.py](pohlig_hellman.py) |
68 changes: 68 additions & 0 deletions
68
Discrete-Logarithm-Problem/Algo-Pohlig-Hellman/ph_orderp2.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from Crypto.Util.number import * | ||
|
||
def pohlig_hellman_p2(g, y, p, e): | ||
""" | ||
Computes `x` for the DLP y = g**x % p in the Group G = {0, 1, 2, ..., p-1}, | ||
given that order of the group `n` is a power of 2, ie. n = p-1 = 2**e. | ||
Note that to solve the DLP using this code, `g` must be the generator. | ||
:parameters: | ||
g : int/long | ||
Generator of the group | ||
y : int/long | ||
Result of g**x % p | ||
p : int/long | ||
Group over which DLP is generated. Commonly p is a prime number | ||
e : int/long | ||
Exponent of 2 in the group order: n = p-1 = 2**e | ||
""" | ||
try: | ||
assert 2**e == p - 1 | ||
except: | ||
print "[-] Error! 2**e is not equal to order!" | ||
return -1 | ||
|
||
k = e | ||
# x is a `k` bit number, max value of x is (2**k - 1) | ||
# x = (c_0 * 2**0) + (c_1 * 2**1) + (c_2 * 2**2) + ... + (c_(k-1) * 2**(k-1)) | ||
# where c_0, c_1, c_2, ..., c_(k-1) belong to {0, 1} | ||
x = "" | ||
|
||
for i in range(1, k+1): | ||
val = pow(y, 2**(k-i), p) | ||
if val == 1: | ||
# val == 1 ==> c_i == 0 (Euler's Theorem) | ||
# digit = c_i | ||
digit = 0 | ||
x += "0" | ||
# y = y*(g**(-c_i*(2**i)) % p) % p = y*(g**0 % p) % p = y % p | ||
y = y | ||
elif val == p-1: | ||
# val == p-1 ==> c_i == 1 | ||
# digit = c_i | ||
digit = 1 | ||
x += "1" | ||
# We need to calculate y = y*(g**(-c_i*(2**i)) % p) % p | ||
# Computed using Step-1 and Step-2 | ||
# Step-1: multiplier = g**(2**(i-1)) % p | ||
multiplier = pow(g, digit*(2**(i-1)), p) | ||
# To calculate inverse of `multiplier` mod p, their GCD should be equal to 1 | ||
if GCD(multiplier, p) != 1: | ||
print "[-] GCD != 1, inverse cannot be calculated. Check your code!" | ||
return -1 | ||
# Step-2: y = y*(g**(-2**(i-1)) % p) % p | ||
y = (y*inverse(multiplier, p)) % p | ||
else: | ||
|
||
print "[-] Some error encountered! Check your code!" | ||
return -1 | ||
# Values of c_i are appended to `x` in reverse order | ||
return int(x[::-1], 2) | ||
|
||
if __name__ == "__main__": | ||
try: | ||
assert pow(3, pohlig_hellman_p2(3, 188, 257, 8), 257) == 188 | ||
assert pow(3, pohlig_hellman_p2(3, 46777, 65537, 16), 65537) == 46777 | ||
except: | ||
print "[-] Function implementation incorrect!" |
66 changes: 66 additions & 0 deletions
66
Discrete-Logarithm-Problem/Algo-Pohlig-Hellman/ph_orderpp.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from Crypto.Util.number import * | ||
|
||
def brute_dlp(g, y, p): | ||
mod_size = len(bin(p-1)[2:]) | ||
sol = pow(g, 2, p) | ||
if y == 1: | ||
return 0 | ||
if y == g: | ||
return 1 | ||
if sol == y: | ||
return y | ||
i = 3 | ||
while i <= p-1: | ||
sol = sol*g % p | ||
if sol == y: | ||
return i | ||
i += 1 | ||
return None | ||
|
||
def pohlig_hellman_pp(g, y, p, q, e): | ||
""" | ||
Reference: http://anh.cs.luc.edu/331/notes/PohligHellmanp_k2p.pdf | ||
Computes `x` = a mod (p-1) for the DLP g**x % p == y | ||
in the Group G = {0, 1, 2, ..., p-1} | ||
given that order `n` = p-1 is a power of a small prime, | ||
ie. n = p-1 = q**e, where q is a small prime | ||
:parameters: | ||
g : int/long | ||
Generator of the group | ||
y : int/long | ||
Result of g**x % p | ||
p : int/long | ||
Group over which DLP is generated. Commonly p is a prime number | ||
e : int/long | ||
Exponent of 2 in the group order: n = p-1 = q**e | ||
""" | ||
|
||
try: | ||
assert p-1 == q**e | ||
# Assume q is a factor of p-1 | ||
assert (p-1) % q == 0 | ||
except: | ||
print "[-] Error! q**e not a factor of p-1" | ||
return -1 | ||
|
||
# a = a_0*(q**0) + a_1*(q**1) + a_2*(q**2) + ... + a_(e-1)*(q**(e-1)) + s*(q**e) | ||
# where a_0, a_1, a_2, ..., a_(e-1) belong to {0,1,...,q-1} and s is some integer | ||
a = 0 | ||
|
||
b_j = y | ||
alpha = pow(g, (p-1)/q, p) | ||
for j in range(e): | ||
y_i = pow(b_j, (p-1)/(q**(j+1)), p) | ||
a_j = brute_dlp(alpha, y_i, p) | ||
assert a_j >= 0 and a_j <= q-1 | ||
a += a_j*(q**j) | ||
|
||
multiplier = pow(g, a_j*(q**j), p) | ||
assert GCD(multiplier, p) == 1 | ||
b_j = (b_j * inverse(multiplier, p)) % p | ||
return a | ||
|
||
if __name__ == "__main__": | ||
assert pow(3, pohlig_hellman_pp(3, 188, 257, 2, 8), 257) == 188 |
79 changes: 79 additions & 0 deletions
79
Discrete-Logarithm-Problem/Algo-Pohlig-Hellman/pohlig_hellman.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
from Crypto.Util.number import * | ||
|
||
def crt(list_a, list_m): | ||
try: | ||
assert len(list_a) == len(list_m) | ||
except: | ||
print "[+] Length of list_a should be equal to length of list_m" | ||
return -1 | ||
for i in range(len(list_m)): | ||
for j in range(len(list_m)): | ||
if GCD(list_m[i], list_m[j])!= 1 and i!=j: | ||
print "[+] Moduli should be pairwise co-prime" | ||
return -1 | ||
M = 1 | ||
for i in list_m: | ||
M *= i | ||
list_b = [M/i for i in list_m] | ||
assert len(list_b) == len(list_m) | ||
try: | ||
assert [GCD(list_b[i], list_m[i]) == 1 for i in range(len(list_m))] | ||
list_b_inv = [int(inverse(list_b[i], list_m[i])) for i in range(len(list_m))] | ||
except: | ||
print "[+] Encountered an unusual error while calculating inverse using gmpy2.invert()" | ||
return -1 | ||
x = 0 | ||
for i in range(len(list_m)): | ||
x += list_a[i]*list_b[i]*list_b_inv[i] | ||
return x % M | ||
|
||
def brute_dlp(g, y, p): | ||
mod_size = len(bin(p-1)[2:]) | ||
sol = pow(g, 2, p) | ||
if y == 1: | ||
return 0 | ||
if y == g: | ||
return 1 | ||
if sol == y: | ||
return y | ||
i = 3 | ||
while i <= p-1: | ||
sol = sol*g % p | ||
if sol == y: | ||
return i | ||
i += 1 | ||
return None | ||
|
||
def pohlig_hellman_pp(g, y, p, q, e): | ||
try: | ||
# Assume q is a factor of p-1 | ||
assert (p-1) % q == 0 | ||
except: | ||
print "[-] Error! q**e not a factor of p-1" | ||
return -1 | ||
|
||
# a = a_0*(q**0) + a_1*(q**1) + a_2*(q**2) + ... + a_(e-1)*(q**(e-1)) + s*(q**e) | ||
# where a_0, a_1, a_2, ..., a_(e-1) belong to {0,1,...,q-1} and s is some integer | ||
a = 0 | ||
|
||
b_j = y | ||
alpha = pow(g, (p-1)/q, p) | ||
for j in range(e): | ||
y_i = pow(b_j, (p-1)/(q**(j+1)), p) | ||
a_j = brute_dlp(alpha, y_i, p) | ||
assert a_j >= 0 and a_j <= q-1 | ||
a += a_j*(q**j) | ||
|
||
multiplier = pow(g, a_j*(q**j), p) | ||
assert GCD(multiplier, p) == 1 | ||
b_j = (b_j * inverse(multiplier, p)) % p | ||
return a | ||
|
||
def pohlig_hellman(g, y, p, list_q, list_e): | ||
x_list = [pohlig_hellman_pp(g, y, p, list_q[i], list_e[i]) for i in range(len(list_q))] | ||
mod_list = [list_q[i]**list_e[i] for i in range(len(list_q))] | ||
return crt(x_list, mod_list) | ||
|
||
if __name__ == "__main__": | ||
p = 0xfffffed83c17 | ||
print pohlig_hellman(5, 230152795807443, p, [2, 3, 7, 13, 47, 103, 107, 151], [1, 2, 1, 4, 1, 1, 1, 1]) |
10 changes: 10 additions & 0 deletions
10
Discrete-Logarithm-Problem/Algo-Pollard-Rho/Challenges/Multiplayer-1/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Multiplayer-1 | ||
|
||
1. Challenge Description: [https://ctftime.org/task/6860](https://ctftime.org/task/6860) | ||
2. Writeups: | ||
+ [My writeup](https://ctftime.org/writeup/11832) | ||
|
||
## Directory Contents | ||
1. [server.sage](server.sage)- given encryption script | ||
2. [parameters.sage](parameters.sage) - File containing public EC parameters required for hosting the challenge locally | ||
3. [points.db](points.db) - database essential for challenge hosting |
19 changes: 19 additions & 0 deletions
19
Discrete-Logarithm-Problem/Algo-Pollard-Rho/Challenges/Multiplayer-1/parameters.sage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
param = { "hacklu": | ||
((889774351128949770355298446172353873, 12345, 67890), | ||
# Generator of Subgroup of prime order 73 bits, 79182553273022138539034276599687 to be excact | ||
(238266381988261346751878607720968495, 591153005086204165523829267245014771), | ||
# challenge Q = xP, x random from [0, 79182553273022138539034276599687) | ||
(341454032985370081366658659122300896, 775807209463167910095539163959068826) | ||
) | ||
} | ||
|
||
serverAdress = '0.0.0.0' | ||
serverPort = 23426 | ||
|
||
(p, a, b), (px, py), (qx, qy) = param["hacklu"] | ||
E = EllipticCurve(GF(p), [a, b]) | ||
P = E((px, py)) | ||
Q = E((qx, qy)) | ||
|
||
def is_distinguished_point(p): | ||
return p[0] < 2^(100) |
Binary file added
BIN
+38 KB
Discrete-Logarithm-Problem/Algo-Pollard-Rho/Challenges/Multiplayer-1/points.db
Binary file not shown.
Oops, something went wrong.