python力が問われる問題。
力づく( 総当たり × 総当たり )で解いた。
問題
Easy
166pt Easy
手始めに
encrypt.pyとoutput.txtが渡される
encrypt.py
with open("flag.txt") as f:
flag = f.read().strip()
A = REDACTED
B = REDACTED
plaintext_space = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
assert all(x in plaintext_space for x in flag)
def encrypt(plaintext: str, a: int, b: int) -> str:
ciphertext = ""
for x in plaintext:
if "A" <= x <= "Z":
x = ord(x) - ord("A")
x = (a * x + b) % 26
x = chr(x + ord("A"))
ciphertext += x
return ciphertext
if __name__ == "__main__":
ciphertext = encrypt(flag, a=A, b=B)
print(ciphertext)
文字の置換に使用されているパラメータ
変数A , 変数B が消されている。
output.txt
HLIM{OCLSAQCZASPYFZASRILLCVMC}
FLAG{ を暗号化した結果が
HLIM{ なので,
総当たりで A , B を求めた後,
ciphertextに一致するplaintextを総当たりで求めるソルバーを作成する
solver.py
def encrypt(plaintext: str, a: int, b: int) -> str:
ciphertext = ""
for x in plaintext:
if "A" <= x <= "Z":
x = ord(x) - ord("A")
x = (a * x + b) % 26
x = chr(x + ord("A"))
ciphertext += x
return ciphertext
plaintext_space = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
flag = "FLAG"
A=0
B=0
i = 0
while i < 26:
j = 0
while j < 26:
ciphertext = encrypt(flag, i, j)
if ciphertext == "HLIM":
print("bingo!")
print("A="+str(i))
print("B="+str(j))
A = i
B = j
j = j + 1
i = i + 1
plaintext = ""
ciphertext = "HLIM{OCLSAQCZASPYFZASRILLCVMC}"
for i in ciphertext:
for j in plaintext_space:
c = encrypt(j, A, B)
if c == i:
plaintext += j
print(plaintext)
実行結果
>python sol_cry-easy.py
bingo!
A=5
B=8
FLAG{WELCOMETOCRYPTOCHALLENGE}
ビンゴ!
作問者writeupみたら数学的に解いてる。
作問者writeup