Back to writeups
HTBcryptoVery Easysolved

The Last Dance

3 Jul 2026 · by 0xIDA

Solvers

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 key and iv used to encrypt TWO messages
  • We know the first plaintext exactly (it's in the source)
  • out.txt contains: 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