Hide and seek
2 minutes to read
I have hidden my flag among the elliptic curve points. Go seek!
Challenge contributed by CryptoHack
Challenge files:
Source code analysis
We are given a SageMath script that uses Elliptic Curve Cryptography to encrypt the flag:
from Crypto.Util.number import bytes_to_long
FLAG = bytes_to_long(open("flag.txt", "rb").read().strip()[len("ECSC{"):-1])
proof.arithmetic(False)
p = 1789850433742566803999659961102071018708588095996784752439608585988988036381340404632423562593
a = 62150203092456938230366891668382702110196631396589305390157506915312399058961554609342345998
b = 1005820216843804918712728918305396768000492821656453232969553225956348680715987662653812284211
F = GF(p)
E.<G> = EllipticCurve(F, [a, b])
assert FLAG < G.order()
k = randrange(G.order())
P = k * G
Q = FLAG * P
res = []
for _ in range(42):
a = randrange(G.order())
b = randrange(G.order())
res.append((a, b, a * P + b * Q))
print(res)
We have the curve parameters $a, b, p$, so we can get the generator point $G$. Then, to encrypt the flag, the script takes a random number $k$ and computes $P = k \cdot G$. After that, the script takes the flag (without ECSC{}
) as a decimal number and computes $Q = \mathrm{FLAG} \cdot P$.
Finally, the script gives us $42$ results: $(a, b, a \cdot P + b \cdot Q)$ with $a$ and $b$ random numbers.
Solution
First of all, we notice that the order of $G$ is smooth (all factors are small):
$ sage -q
sage: proof.arithmetic(False)
....: p = 1789850433742566803999659961102071018708588095996784752439608585988988036381340404632423562593
....: a = 62150203092456938230366891668382702110196631396589305390157506915312399058961554609342345998
....: b = 1005820216843804918712728918305396768000492821656453232969553225956348680715987662653812284211
....: F = GF(p)
....: E.<G> = EllipticCurve(F, [a, b])
sage: factor(G.order())
12775224751 * 13026062843 * 18511195699 * 24508446437 * 25961704469 * 28450356619 * 31034521019 * 31982226581 * 32337773063
Therefore, the Discrete Logarithm Problem (ECDLP) is easy to solve using Pohlig-Hellman algorithm. As a result, if we have $P$ and $Q = \mathrm{FLAG} \cdot P$, we can find $\mathrm{FLAG}$.
In order to find $P$ and $Q$, we can take advantage of $2$ outputs:
$$ \begin{cases} R_1 = a_1 \cdot P + b_1 \cdot Q \\ R_2 = a_2 \cdot P + b_2 \cdot Q \end{cases} $$
Using both equations, we can isolate $P$ and $Q$:
$$ \begin{cases} P = (a_1 b_1^{-1} - a_2 b_2^{-1})^{-1} \cdot (b_1^{-1} \cdot R_1 - b_2^{-1} \cdot R_2) \\ Q = (a_1^{-1} b_1 - a_2^{-1} b_2)^{-1} \cdot (a_1^{-1} \cdot R_1 - a_2^{-1} \cdot R_2) \end{cases} $$
Flag
And now we just solve the ECDLP $Q = \mathrm{FLAG} \cdot P$ and get the flag:
$ python3 solve.py
ECSC{l0g_pr0perty_w0rks_d1scr3t3ly_9d03dde5}
The full script can be found in here: solve.py
.