Golden Ticket
Golden Ticket (idek 2024)
So we’re given the following:
from Crypto.Util.number import *
#Some magic from Willy Wonka
def chocolate_generator(m:int) -> int:
p = 396430433566694153228963024068183195900644000015629930982017434859080008533624204265038366113052353086248115602503012179807206251960510130759852727353283868788493357310003786807
return (pow(13, m, p) + pow(37, m, p)) % p
#The golden ticket is hiding inside chocolate
flag = b"idek{REDACTED}"
golden_ticket = bytes_to_long(flag)
flag_chocolate = chocolate_generator(golden_ticket)
chocolate_bag = []
#Willy Wonka is making chocolates
for i in range(golden_ticket):
chocolate_bag.append(chocolate_generator(i))
#And he put the golden ticket at the end
chocolate_bag.append(flag_chocolate)
#Augustus ate lots of chocolates, but he can't eat all cuz he is full now :D
remain = chocolate_bag[-2:]
#Can you help Charles get the golden ticket?
print(remain)
#[88952575866827947965983024351948428571644045481852955585307229868427303211803239917835211249629755846575548754617810635567272526061976590304647326424871380247801316189016325247, 67077340815509559968966395605991498895734870241569147039932716484176494534953008553337442440573747593113271897771706973941604973691227887232994456813209749283078720189994152242]
So the chocolate_generator
function gives us
$$ cg(x) = 13^x + 37^x \mod p $$
And we’re given the following values of it, flag-1
and flag
. So we have
$$ \begin{matrix} cg(flag-1) &=& 13^{flag-1} &+& 37^{flag-1} \\ cg(flag) &=& 13^{flag} &+& 37^{flag} \\ \end{matrix} $$
So we multiply the top by 37 and 13 to make everything have the same powers
$$ \begin{matrix} 37\times 13\times cg(flag-1) &=& 37\times 13^{flag} &+& 13\times 37^{flag} \\ cg(flag) &=& 13^{flag} &+& 37^{flag} \\ \end{matrix} $$
And then subtract the bottom times 37 from the top to get
$$ \begin{matrix} 37\times 13\times cg(flag-1) - 37\times cg(flag) &=& -24\times 37^{flag} \\ \end{matrix} $$
Now $p-1$ is the size of the multiplication group of $p$, and it turns out it is entirely composed of small factors. So Pohlig-Helman applies here, and the discrete log can be computed quickly in $p$. So in sage we can simply do (since it will automatically apply Pohlig-Helman when solving in $p$)
p=396430433566694153228963024068183195900644000015629930982017434859080008533624204265038366113052353086248115602503012179807206251960510130759852727353283868788493357310003786807
a,b = [88952575866827947965983024351948428571644045481852955585307229868427303211803239917835211249629755846575548754617810635567272526061976590304647326424871380247801316189016325247, 67077340815509559968966395605991498895734870241569147039932716484176494534953008553337442440573747593113271897771706973941604973691227887232994456813209749283078720189994152242]
e_msg = (37*13*a-37*b) * pow(-24,-1,p)
msg = GF(p)(e_msg).log(37)
print(msg.to_bytes(128, 'big').replace(b"\x00",0))