ACSC Quals 2024
solution for easy crypto challenge in ACSC Quals 2024
RSA stream 2
chal_redacted.py
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
from Crypto.Util.number import getPrime
import random
import re
p = getPrime(512)
q = getPrime(512)
e = 65537
n = p * q
d = pow(e, -1, (p - 1) * (q - 1))
m = random.randrange(2, n)
c = pow(m, e, n)
text = open(__file__, "rb").read()
ciphertext = []
for b in text:
o = 0
for i in range(8):
bit = ((b >> i) & 1) ^ (pow(c, d, n) % 2)
c = pow(2, e, n) * c % n
o |= bit << i
ciphertext.append(o)
open("chal.py.enc", "wb").write(bytes(ciphertext))
redacted = re.sub("flag = \"ACSC{(.*)}\"", "flag = \"ACSC{*REDACTED*}\"", text.decode())
open("chal_redacted.py", "w").write(redacted)
print("n =", n)
# flag = "ACSC{*REDACTED*}"
#n = 106362501554841064194577568116396970220283331737204934476094342453631371019436358690202478515939055516494154100515877207971106228571414627683384402398675083671402934728618597363851077199115947762311354572964575991772382483212319128505930401921511379458337207325937798266018097816644148971496405740419848020747
This is how encryptation work:
First bit of chall file (which contains the flag) xor with , $(m\mod n)\mod 2$, the second bit xor with
$(2*m \mod n) \pmod 2$, $…$
Then chall file redacted flag
So we can only get last bit of $ m \pmod n$, $(2 * m \pmod n)$, … but it is enough to get $m$ this is because 2 $*$ m always even so if it mod n - odd number two cases appear:
- If result is even which mean m $ \leq $ n/2
- Else m $>$ n/2
n.bit_length() = 1024, we only need 128 chars to search
So that, I use binary search to find m ; however, the actual $m’$ is near it.
solve.py
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
import random
from Crypto.Util.number import getPrime
from output import n
from tqdm import*
text = open("chal_redacted.py", "rb").read()
ctext = open("chal.py.enc", "rb").read()
check=""
for b, c in zip(text, ctext):
o = 0
for i in range(8):
bit = ((b >> i) & 1) ^ ((c>>i)&1)
check += str(bit)
k=1
lb, ub = 0, n
for i in trange(n.bit_length()):
if check[k]=="1":
lb = (ub+lb)//2
k+=1
else:
ub = (ub+lb)//2
k+=1
for bound in trange(-2000, 2000):
m = ub+bound
ciphertexts = []
ctext = open("chal.py.enc", "rb").read()
for c in ctext:
o = 0
for i in range(8):
bit = ((c >> i) & 1) ^ ((m) % 2)
m = (2*m)%n
o |= bit << i
ciphertexts.append(o)
if b"ACSC{" in bytes(ciphertexts):
print(f"{bound = }")
open("chal_solve.py", "wb").write(bytes(ciphertexts))
break
This post is licensed under CC BY 4.0 by the author.