Skip to content

Commit ac624c5

Browse files
committed
Participate HITCON CTF 2022
1 parent c261bbc commit ac624c5

File tree

4 files changed

+268
-0
lines changed

4 files changed

+268
-0
lines changed

HITCON/2022/secret/output.txt

+2
Large diffs are not rendered by default.

HITCON/2022/secret/prob.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import random, os
2+
from Crypto.Util.number import getPrime, bytes_to_long
3+
4+
p = getPrime(1024)
5+
q = getPrime(1024)
6+
n = p * q
7+
8+
flag = open('flag','rb').read()
9+
pad_length = 256 - len(flag)
10+
m = bytes_to_long(os.urandom(pad_length) + flag)
11+
assert(m < n)
12+
es = [random.randint(1, 2**512) for _ in range(64)]
13+
cs = [pow(m, p + e, n) for e in es]
14+
print(es)
15+
print(cs)

HITCON/2022/secret/solver.sage

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import ast
2+
import random
3+
from multiprocessing import Pool
4+
5+
from Crypto.Util.number import inverse, long_to_bytes
6+
7+
with open("output.txt", "r") as f:
8+
es = ast.literal_eval(f.readline())
9+
cs = ast.literal_eval(f.readline())
10+
11+
12+
def coeff_mul(coeffs, n=None):
13+
acc_e = 0
14+
acc_c = 1
15+
for (e, c, coeff) in zip(es, cs, coeffs):
16+
acc_e += coeff * e
17+
if n is None:
18+
acc_c *= pow(c, coeff)
19+
else:
20+
acc_c *= pow(c, coeff, n)
21+
22+
return (acc_e, int(acc_c))
23+
24+
25+
def work(work_arg):
26+
(basis, n) = work_arg
27+
28+
if sum(basis) != 0 or basis[len(basis) - 1] != 0 or basis[len(basis) - 2] != 0:
29+
return None
30+
31+
first = []
32+
second = []
33+
34+
for i in range(len(basis) - 1):
35+
if basis[i] < 0:
36+
first.append(-basis[i])
37+
second.append(0)
38+
else:
39+
first.append(0)
40+
second.append(basis[i])
41+
42+
return abs(coeff_mul(first, n)[1] - coeff_mul(second, n)[1])
43+
44+
45+
# First stage - find N
46+
n = None
47+
bits = 0
48+
49+
small_prime = []
50+
51+
for i in range(2, 100):
52+
if is_prime(i):
53+
small_prime.append(i)
54+
55+
with Pool() as pool:
56+
while True:
57+
mat = []
58+
scale = 2**64
59+
60+
for (i, e) in enumerate(es):
61+
row = [1 if i == j else 0 for j in range(len(es))]
62+
row.append(e * scale)
63+
row.append(scale)
64+
mat.append(row)
65+
66+
bases = Matrix(mat).LLL()
67+
worklist = [(basis, n) for basis in bases]
68+
for cand in pool.map(work, worklist):
69+
if cand is None:
70+
continue
71+
72+
if n is None:
73+
n = cand
74+
else:
75+
n = gcd(n, cand)
76+
77+
bits = int(n).bit_length()
78+
print(f"bit_length of N: {bits}")
79+
80+
for prime in small_prime:
81+
while n % prime == 0:
82+
n = n // prime
83+
print(f"bit_length of N: {bits}")
84+
85+
if bits == 2048:
86+
break
87+
88+
# Second stage - recover m
89+
if es[0] > es[1]:
90+
big = 0
91+
small = 1
92+
else:
93+
big = 1
94+
small = 0
95+
96+
first_e = es[big] - es[small]
97+
first_c = cs[big] * inverse(cs[small], n) % n
98+
99+
if es[3] > es[4]:
100+
big = 3
101+
small = 4
102+
else:
103+
big = 4
104+
small = 3
105+
106+
second_e = es[big] - es[small]
107+
second_c = cs[big] * inverse(cs[small], n) % n
108+
109+
110+
def egcd(a, b):
111+
if a == 0:
112+
return (b, 0, 1)
113+
else:
114+
g, y, x = egcd(b % a, a)
115+
return (g, x - (b // a) * y, y)
116+
117+
118+
g, x, y = egcd(first_e, second_e)
119+
assert g == 1
120+
121+
m = pow(first_c, x, n) * pow(second_c, y, n) % n
122+
print(long_to_bytes(int(m)))

HITCON/2022/secret/solver.sage.py

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
3+
# This file was *autogenerated* from the file solver.sage
4+
from sage.all_cmdline import * # import sage library
5+
6+
_sage_const_0 = Integer(0); _sage_const_1 = Integer(1); _sage_const_2 = Integer(2); _sage_const_100 = Integer(100); _sage_const_64 = Integer(64); _sage_const_2048 = Integer(2048); _sage_const_3 = Integer(3); _sage_const_4 = Integer(4)
7+
import ast
8+
import random
9+
from multiprocessing import Pool
10+
11+
from Crypto.Util.number import inverse, long_to_bytes
12+
13+
with open("output.txt", "r") as f:
14+
es = ast.literal_eval(f.readline())
15+
cs = ast.literal_eval(f.readline())
16+
17+
18+
def coeff_mul(coeffs, n=None):
19+
acc_e = _sage_const_0
20+
acc_c = _sage_const_1
21+
for (e, c, coeff) in zip(es, cs, coeffs):
22+
acc_e += coeff * e
23+
if n is None:
24+
acc_c *= pow(c, coeff)
25+
else:
26+
acc_c *= pow(c, coeff, n)
27+
28+
return (acc_e, int(acc_c))
29+
30+
31+
def work(work_arg):
32+
(basis, n) = work_arg
33+
34+
if sum(basis) != _sage_const_0 or basis[len(basis) - _sage_const_1 ] != _sage_const_0 or basis[len(basis) - _sage_const_2 ] != _sage_const_0 :
35+
return None
36+
37+
first = []
38+
second = []
39+
40+
for i in range(len(basis) - _sage_const_1 ):
41+
if basis[i] < _sage_const_0 :
42+
first.append(-basis[i])
43+
second.append(_sage_const_0 )
44+
else:
45+
first.append(_sage_const_0 )
46+
second.append(basis[i])
47+
48+
return abs(coeff_mul(first, n)[_sage_const_1 ] - coeff_mul(second, n)[_sage_const_1 ])
49+
50+
51+
# First stage - find N
52+
n = None
53+
bits = _sage_const_0
54+
55+
small_prime = []
56+
57+
for i in range(_sage_const_2 , _sage_const_100 ):
58+
if is_prime(i):
59+
small_prime.append(i)
60+
61+
with Pool() as pool:
62+
while True:
63+
mat = []
64+
scale = _sage_const_2 **_sage_const_64
65+
66+
for (i, e) in enumerate(es):
67+
row = [_sage_const_1 if i == j else _sage_const_0 for j in range(len(es))]
68+
row.append(e * scale)
69+
row.append(scale)
70+
mat.append(row)
71+
72+
bases = Matrix(mat).LLL()
73+
worklist = [(basis, n) for basis in bases]
74+
for cand in pool.map(work, worklist):
75+
if cand is None:
76+
continue
77+
78+
if n is None:
79+
n = cand
80+
else:
81+
n = gcd(n, cand)
82+
83+
bits = int(n).bit_length()
84+
print(f"bit_length of N: {bits}")
85+
86+
for prime in small_prime:
87+
while n % prime == _sage_const_0 :
88+
n = n // prime
89+
print(f"bit_length of N: {bits}")
90+
91+
if bits == _sage_const_2048 :
92+
break
93+
94+
# Second stage - recover m
95+
if es[_sage_const_0 ] > es[_sage_const_1 ]:
96+
big = _sage_const_0
97+
small = _sage_const_1
98+
else:
99+
big = _sage_const_1
100+
small = _sage_const_0
101+
102+
first_e = es[big] - es[small]
103+
first_c = cs[big] * inverse(cs[small], n) % n
104+
105+
if es[_sage_const_3 ] > es[_sage_const_4 ]:
106+
big = _sage_const_3
107+
small = _sage_const_4
108+
else:
109+
big = _sage_const_4
110+
small = _sage_const_3
111+
112+
second_e = es[big] - es[small]
113+
second_c = cs[big] * inverse(cs[small], n) % n
114+
115+
116+
def egcd(a, b):
117+
if a == _sage_const_0 :
118+
return (b, _sage_const_0 , _sage_const_1 )
119+
else:
120+
g, y, x = egcd(b % a, a)
121+
return (g, x - (b // a) * y, y)
122+
123+
124+
g, x, y = egcd(first_e, second_e)
125+
assert g == _sage_const_1
126+
127+
m = pow(first_c, x, n) * pow(second_c, y, n) % n
128+
print(long_to_bytes(int(m)))
129+

0 commit comments

Comments
 (0)