[SECCON Beginners CTF 2022] coughingfox

以下のソースコードで暗号化されたファイルを復号化する問題

from random import shuffle

flag = b"ctf4b{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}"

cipher = []

for i in range(len(flag)):
    f = flag[i]
    c = (f + i)**2 + i
    cipher.append(c)

shuffle(cipher) #リストの要素をシャッフルする
print("cipher =", cipher)

cとfの関係を式変形すると以下が得られる.

従ってc - i が平方数になるとき正しい平文とその場所を得られる.

以下がソルバ

cipher = [12147, 20481, 7073, 10408, 26615, 19066, 19363, 10852, 11705, 17445, 3028, 10640, 10623, 13243, 5789, 17436, 12348, 10818, 15891, 2818, 13690, 11671, 6410, 16649, 15905, 22240, 7096, 9801, 6090, 9624, 16660, 18531, 22533, 24381, 14909, 17705, 16389, 21346, 19626, 29977, 23452, 14895, 17452, 17733, 22235, 24687, 15649, 21941, 11472]

plain = [""] * len(cipher)
for c in cipher:
    for i in range(len(cipher)):
        sqrt_c = (c - i) ** 0.5
        if sqrt_c.is_integer():
            plain[i] = chr(int(sqrt_c - i))
            break
print("".join(plain))

ctf4b{Hey,Fox?YouCanNotTearThatHouseDown,CanYou?}