The Last Dance
Author: 0xIDA
Platform: HTB · Category: crypto · Difficulty: Very Easy
Solvers
Summary
A stream-cipher keystream reuse attack. The challenge encrypts both a known message and the FLAG with the same ChaCha20 key+nonce, allowing the FLAG to be recovered by XORing the two ciphertexts and the known plaintext.
Analysis
From source.py:
- ChaCha20 stream cipher with a 32-byte key and 12-byte nonce
- Same
keyandivused to encrypt TWO messages - We know the first plaintext exactly (it's in the source)
out.txtcontains: IV | encrypted_message | encrypted_flag
This is the textbook stream-cipher key-reuse vulnerability, also known as the "two-time pad."
Exploitation
Since ChaCha20 is a stream cipher:
C1 = P1 ⊕ keystream
C2 = P2 ⊕ keystream
XOR cancels the keystream:
C1 ⊕ C2 = P1 ⊕ P2
Then isolate P2:
P2 = C1 ⊕ C2 ⊕ P1
Simple one-liner:
flag = bytes(a ^ b ^ c for a, b, c in zip(enc_msg, enc_flag, known_msg))
Key Findings
- The keystream is identical for both encryption calls because the same
(key, nonce)pair is used - The known plaintext message is 156 bytes; the encrypted flag is 51 bytes
- The keystream for the first 51 bytes is identical for both messages
Flag
HTB{und3r57AnD1n9_57R3aM_C1PH3R5_15_51mPl3_a5_7Ha7}
Decoded: "Understanding Stream Ciphers is Simple as That"
Lessons Learned
- Never reuse a key+nonce pair with a stream cipher — it gives away the keystream
- This is the exact same vulnerability as a two-time pad in one-time pad encryption
- Always check if source.py shows the same key/IV being used for multiple encryptions — it's a dead giveaway for this attack