Lion Cipher Lab

Recover a secret token with a timing attack on a non-constant-time comparison — then fix it with a constant-time compare

Why it matters

Almost every system that checks a secret — an API token, an HMAC signature on a webhook, a password reset token, a session id — ends up comparing two byte strings and deciding equal or not equal. The obvious way to write that, `submitted == real`, hides a genuine vulnerability: a normal comparison is optimised to stop the instant it finds the first byte that differs. So a guess that is right in the first byte but wrong in the second takes longer to reject than a guess that is wrong in the very first byte, and a guess that is right in the first three bytes takes longer still. The amount of…

What you'll learn

Steps in this lab

  1. First: this is your machine, and what a timing side-channel actually is
  2. Why an early-return compare leaks how many bytes you got right
  3. Set up Python and write the insecure comparison
  4. Build the tiny offline victim endpoint
  5. The attack harness — and why the MINIMUM beats the mean
  6. Run the attack: recover the secret one byte at a time (the BEFORE)
  7. The fix: hmac.compare_digest, then re-run the exact same attack (the AFTER)
  8. The honest negative: why remote timing attacks are hard, and where the compare hides
  9. The judgment: always constant-time for secrets, and how a pro thinks about it

Open the full interactive lab →