Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pwang00
GitHub Repository: pwang00/Cryptographic-Attacks
Path: blob/master/Public Key/RSA/hastad.sage
336 views
1
"""
2
Sage implementation of Hastad's broadcast attack for small public exponent and multiple message/ciphertext pairs
3
"""
4
5
import binascii
6
import random
7
8
def hastad(ciphertexts, moduli, e=3):
9
"""
10
Performs a Hastad's attack on non-padded ciphertexts
11
M = Message
12
ciphertexts = ciphertext array
13
moduli = moduli array
14
"""
15
16
if not (len(moduli) == len(ciphertexts) == e):
17
raise RuntimeError("Moduli and ciphertext arrays have to be equal in length, and contain at least as many elements as e")
18
19
M = crt(ciphertexts, moduli).nth_root(e)
20
return M
21
22
def linear_padding(ciphertexts, moduli, pad_array, const_array=(), e=3, eps=1/8):
23
if not(len(ciphertexts) == len(moduli) == len(pad_array) == len(const_array) == e):
24
raise RuntimeError("Moduli and ciphertext arrays have to be equal in length, and contain at least as many elements as e")
25
26
'''
27
Initialization with placeholders
28
ciphertexts: ciphertext array
29
T_array: Chinese Remainder Theorem coefficients
30
moduli: Modulus array
31
pad_array: Linear coefficient of padding applied to the message during encryption
32
const_array: constant pad added to message during encryption (optional)
33
'''
34
T_array = [Integer(0)]*e
35
crt_array = [Integer(0)]*e
36
polynomial_array = []
37
38
for i in range(e):
39
crt_array = [0]*e
40
crt_array[i] = 1
41
T_array[i] = Integer(crt(crt_array,moduli))
42
43
G.<x> = PolynomialRing(Zmod(prod(moduli)))
44
for i in range(e):
45
polynomial_array += [T_array[i]*((pad_array[i]*x+const_array[i])^e - Integer(ciphertexts[i]))] #Representation of polynomial f(x) = (A*x + b) ^ e - C where (A*x + b) is the padding polynomial
46
47
g = sum(polynomial_array).monic() #Creates a monic polynomial from the sum of the individual polynomials
48
roots = g.small_roots(epsilon=eps)
49
return roots[0] if len(roots) >= 1 else -1
50
51
52
def convert_to_int(message):
53
return int(message.encode("hex"),16)
54
55
def decode(message):
56
return message.decode("hex")
57
58
""" Test / Proof of Correctness """
59
60
def test_no_padding():
61
m = convert_to_int("hello")
62
e = 3
63
bound = 2^1024
64
ciphertexts = []
65
moduli = []
66
67
for i in range(e):
68
p = random_prime(bound,proof=false)
69
q = random_prime(bound,proof=false)
70
n = p*q
71
c = Integer(pow(m, e, n))
72
moduli += [Integer(n)]
73
ciphertexts += [c]
74
75
assert hastad(ciphertexts,moduli,e) == m
76
print("Success! The recovered message is equal to: " + hex(m)[2:].decode("hex"))
77
78
return 0
79
80
def test_linear_padding():
81
moduli = []
82
ciphertexts = []
83
pad_array = []
84
const_array = []
85
e = 3
86
pad_bound = 2^512
87
prime_bound = 2^1024
88
m = convert_to_int("p00rth0_th3_p00r")
89
90
for i in range(e):
91
pad = random.randint(0,pad_bound)
92
constant = random.randint(0,pad_bound)
93
pad_array += [pad]
94
const_array += [constant]
95
p = random_prime(prime_bound,proof=false)
96
q = random_prime(prime_bound,proof=false)
97
n = p*q
98
moduli += [n]
99
ciphertexts.append(pow(pad * m + constant,e,n))
100
101
assert linear_padding(ciphertexts, moduli, pad_array, const_array) == m
102
print("Success!")
103
return 0
104
105