Overview
ChaCha20を使用している。 key/nonceの再利用による脆弱性が存在する。
Solution
ChaCha20はストリーム暗号で、keyとnonceからkeystreamを生成し、平文とXORすることで暗号文を得る。
ChaCha20の入力にはkey・counter・nonceが含まれ、出力としてkeystreamが生成される。
従って、同じ (key, nonce) で暗号器を毎回初期化し直す実装では、同じ鍵ストリームが再生成されてしまう。
すると既知の平文msgとencrypted_msgからkeystreamを復元でき、encrypted_flag XOR keystreamによりflagを復号できる。
Exploit
from binascii import unhexlify
msg = b"Daily AlpacaHack is a daily CTF challenge with a fun new puzzle every day."
ct_msg_hex = "aa9054e15ee209d458784a70bab6a5d62523f26eef2458cb3d48ccc6122fba1d75733c17c70a908a64b45b0caaf8d0e3bd30bcc0900283af88d82d4020cdacf7eaa5685ccf443776b4d9"
ct_flag_hex = "af9d4dec44a333d44d2e0e62ade1f5c95a38e438eb6a0acf0b10c1b92513cf627828250ff43cbbae42db6244a3"
ct_msg = unhexlify(ct_msg_hex)
ct_flag = unhexlify(ct_flag_hex)
keystream = bytes(c ^ p for c, p in zip(ct_msg, msg))
flag = bytes(c ^ k for c, k in zip(ct_flag, keystream[:len(ct_flag)]))
print(flag.decode(errors="replace"))