1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
n = 115792089237316195423570985008687907852837564279074904382605163141518161494337
# Given signatures and messages
m1 = b'32748923ur8934u893ygf893h34t3453453'
r1 = 18507930132802310344248699822628576170242868593944128167302942018134209256936
s1 = 23965013559564325260453725916491832279556345092147805659950905735422363429946
m2 = b'ehfw9h8r039u82678ifjewf9024r2323423'
r2 = 61645219796227967861807301237829197706412124807702206247291322591426944615554
s2 = 84283844402102709520391794221564573160907887711307574424747605446691209453247
h1 = int.from_bytes(sha256(m1).digest(), 'big')
h2 = int.from_bytes(sha256(m2).digest(), 'big')
# From s = k^(-1) * (h + d * r) % n, we have k = s * (h + d * r)^(-1) % n
# No, it's k = s^(-1) * (h + d * r) % n. This was correct in the previous script.
# Let k1 = pow(s1, -1, n) * (h1 + d * r1) % n
# Let k2 = pow(s2, -1, n) * (h2 + d * r2) % n
s1_inv = pow(s1, -1, n)
s2_inv = pow(s2, -1, n)
# k2 = (7 * k1^2 + 3 * k1 + 11) % n
# Substitute k1 and k2 into the equation:
# s2_inv * (h2 + d * r2) = 7 * (s1_inv * (h1 + d * r1))^2 + 3 * (s1_inv * (h1 + d * r1)) + 11 (mod n)
# Let x = d
# A = s2_inv * r2
# B = s2_inv * h2
# C = s1_inv * r1
# D = s1_inv * h1
# B + A*x = 7 * (D + C*x)^2 + 3 * (D + C*x) + 11 (mod n)
# B + A*x = 7 * (D^2 + 2*C*D*x + C^2*x^2) + 3*D + 3*C*x + 11 (mod n)
# B + A*x = 7*D^2 + 14*C*D*x + 7*C^2*x^2 + 3*D + 3*C*x + 11 (mod n)
# Rearranging to form a quadratic equation: Ax^2 + Bx + C = 0 (mod n)
# (7*C^2)*x^2 + (14*C*D + 3*C - A)*x + (7*D^2 + 3*D + 11 - B) = 0 (mod n)
# Coefficients for the quadratic equation Ax^2 + Bx + C = 0 (mod n)
coeff_A = (7 * pow(s1_inv, 2, n) * pow(r1, 2, n)) % n
coeff_B = (14 * pow(s1_inv, 2, n) * r1 * h1 + 3 * s1_inv * r1 - s2_inv * r2) % n
coeff_C = (7 * pow(s1_inv, 2, n) * pow(h1, 2, n) + 3 * s1_inv * h1 + 11 - s2_inv * h2) % n
# Function to find modular square root (Tonelli-Shanks algorithm for prime modulus)
def legendre_symbol(a, p):
ls = pow(a, (p - 1) // 2, p)
return -1 if ls == p - 1 else ls
def mod_sqrt(a, p):
if legendre_symbol(a, p) != 1:
return None
if p % 4 == 3:
return pow(a, (p + 1) // 4, p)
# Tonelli-Shanks for p % 4 == 1
q = p - 1
s = 0
while q % 2 == 0:
q //= 2
s += 1
if s == 1:
return pow(a, (p + 1) // 4, p)
z = 2
while legendre_symbol(z, p) != -1:
z += 1
m = s
c = pow(z, q, p)
t = pow(a, q, p)
r = pow(a, (q + 1) // 2, p)
while True:
if t == 0:
return 0
if t == 1:
return r
i = 0
temp_t = t
while temp_t != 1 and i < m:
temp_t = pow(temp_t, 2, p)
i += 1
if i == m:
return None
b = pow(c, pow(2, m - i - 1), p)
m = i
c = pow(b, 2, p)
t = (t * c) % p
r = (r * b) % p
# Solve the quadratic congruence: coeff_A * x^2 + coeff_B * x + coeff_C = 0 (mod n)
# x = (-coeff_B +/- sqrt(coeff_B^2 - 4*coeff_A*coeff_C)) * (2*coeff_A)^(-1) (mod n)
discriminant = (pow(coeff_B, 2, n) - 4 * coeff_A * coeff_C) % n
sqrt_discriminant = mod_sqrt(discriminant, n)
if sqrt_discriminant is None:
print("No modular square root found for the discriminant.")
else:
two_A_inv = pow(2 * coeff_A, -1, n)
d1 = ((-coeff_B + sqrt_discriminant) * two_A_inv) % n
d2 = ((-coeff_B - sqrt_discriminant) * two_A_inv) % n
print(f"Possible private keys: d1={d1}, d2={d2}")
# Given encrypted flag
encrypted_flag = b'\xa7\x13\xd5j\x10*\xc9\x04\xda\x8b\xaaf\xde\xae\xdc\xdb\xb7T\xcd\x8b\xc9K\xf4\xb4^p\x8da\x1bS\xef\x92\xaf\x03\xe9\xc2\x0c\x8c\x83\x83\xf9\xc6\xc7\t\xf9\x9cp\x9d'
# Try decrypting with d1
key1 = sha256(str(d1).encode()).digest()
cipher1 = AES.new(key=key1, mode=AES.MODE_ECB)
try:
decrypted_flag1 = unpad(cipher1.decrypt(encrypted_flag), AES.block_size)
print(f"Decrypted flag with d1: {decrypted_flag1}")
except ValueError as e:
print(f"Decryption with d1 failed: {e}")
# Try decrypting with d2
key2 = sha256(str(d2).encode()).digest()
cipher2 = AES.new(key=key2, mode=AES.MODE_ECB)
try:
decrypted_flag2 = unpad(cipher2.decrypt(encrypted_flag), AES.block_size)
print(f"Decrypted flag with d2: {decrypted_flag2}")
except ValueError as e:
print(f"Decryption with d2 failed: {e}")
|