the shortest crypto chal
Category
Cryptography
Tags
We are given the following Python code in chal.py
:
from Crypto.Cipher import AES
from hashlib import md5
from secret import a,b,c,d, FLAG
assert a**4 + b**4 == c**4 + d**4 + 17 and max(a,b,c,d) < 2e4 and AES.new( f"{a*b*c*d}".zfill(16).encode() , AES.MODE_ECB).encrypt(FLAG).hex() == "41593455378fed8c3bd344827a193bde7ec2044a3f7a3ca6fb77448e9de55155"
This script defines an assertion over 4 integers a
, b
, c
, d
, such that their fourth powers satisfy a specific relationship, and a given AES-ECB ciphertext must be the encryption of the flag using the key derived from a*b*c*d
.
Observations
- The flag is encrypted with AES in ECB mode.
- The encryption key is derived by computing the product
a*b*c*d
, converting it to a zero-padded string of length 16. - The values
a, b, c, d
are all less than 20,000. - The equation to solve is:
a^4 + b^4 = c^4 + d^4 + 17
which is a Diophantine equation with a small offset.
This resembles a variation of the taxicab number problem (sums of two fourth powers), which is solvable by precomputing possibilities.
Strategy
To recover the plaintext flag:
- Precompute all valid right-hand sides (RHS) of the equation
c^4 + d^4
for all1 <= c,d < n
withd <= c
- For each possible pair
(a, b)
(withb <= a
), compute the left-hand sidea^4 + b^4 - 17
. - Binary search the RHS list for a match. If found:
- Compute the possible c and check if d^4 = lhs - c^4 gives an integer d.
- If all constraints are met, compute
k = str(a*b*c*d).zfill(16).encode()
and decrypt the ciphertext. - If the plaintext starts with
uiuctf{
, we have found the correct key and decrypted the flag.
Solver
from Crypto.Cipher import AES
from array import array
from bisect import bisect_left
n = 20000
fourth = [i**4 for i in range(n)]
# Precompute all c^4 + d^4 pairs
rhs = sorted(fourth[c] + fourth[d] for c in range(1, n) for d in range(1, c + 1))
ct = bytes.fromhex("41593455378fed8c3bd344827a193bde7ec2044a3f7a3ca6fb77448e9de55155")
for a in range(1, n):
for b in range(1, a + 1):
t = fourth[a] + fourth[b] - 17
if t > rhs[-1]: break
if rhs[bisect_left(rhs, t)] != t: continue
for c in range(1, n):
d4 = t - fourth[c]
if d4 < 1: break
d = round(d4 ** 0.25)
if 1 <= d <= c and fourth[d] == d4:
k = str(a * b * c * d).zfill(16).encode()
pt = AES.new(k, AES.MODE_ECB).decrypt(ct)
if pt.startswith(b'uiuctf{'):
print(pt.decode())
exit()
the shortest crypto chal Flag:
uiuctf{D1oPh4nTine__Destr0yer__}