Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pwang00
GitHub Repository: pwang00/Cryptographic-Attacks
Path: blob/master/Public Key/RSA/coppersmith_short_pad.sage
336 views
1
import random
2
import binascii
3
4
def coppersmith_short_pad(C1, C2, N, e = 3, eps = 1/25):
5
P.<x, y> = PolynomialRing(Zmod(N))
6
P2.<y> = PolynomialRing(Zmod(N))
7
8
g1 = (x^e - C1).change_ring(P2)
9
g2 = ((x + y)^e - C2).change_ring(P2)
10
11
# Changes the base ring to Z_N[y] and finds resultant of g1 and g2 in x
12
res = g1.resultant(g2, variable=x)
13
14
# coppersmith's small_roots only works over univariate polynomial rings, so we
15
# convert the resulting polynomial to its univariate form and take the coefficients modulo N
16
# Then we can call the sage's small_roots function and obtain the delta between m_1 and m_2.
17
# Play around with these parameters: (epsilon, beta, X)
18
roots = res.univariate_polynomial().change_ring(Zmod(N))\
19
.small_roots(epsilon=eps)
20
21
return roots[0]
22
23
def franklin_reiter(C1, C2, N, r, e=3):
24
P.<x> = PolynomialRing(Zmod(N))
25
equations = [x ^ e - C1, (x + r) ^ e - C2]
26
g1, g2 = equations
27
return -composite_gcd(g1,g2).coefficients()[0]
28
29
30
# I should implement something to divide the resulting message by some power of 2^i
31
def recover_message(C1, C2, N, e = 3):
32
delta = coppersmith_short_pad(C1, C2, N)
33
recovered = franklin_reiter(C1, C2, N, delta)
34
return recovered
35
36
def composite_gcd(g1,g2):
37
return g1.monic() if g2 == 0 else composite_gcd(g2, g1 % g2)
38
39
# Takes a long time for larger values and smaller epsilon
40
def test():
41
N = random_prime(2^512, proof=False) * random_prime(2^512, proof=False)
42
e = 3
43
44
m = Integer(math.log(N, 2) // e^2)
45
46
r1 = random.randint(1, pow(2, m))
47
r2 = random.randint(1, pow(2, m))
48
49
M = int(binascii.hexlify(b"hello"), 16)
50
C1 = pow(pow(2, m) * M + r1, e, N)
51
C2 = pow(pow(2, m) * M + r2, e, N)
52
53
# Using eps = 1/125 is slooooowww
54
print(coppersmith_short_pad(C1, C2, N, eps=1/200))
55
print(recover_message(C1, C2, N))
56
57
if __name__ == "__main__":
58
test()
59
60