Lion Cipher Lab

Parse an X.509 certificate byte by byte, with a DER decoder you write from scratch

Why it matters

Every TLS connection, signed update and passkey registration starts with a program reading an X.509 certificate out of raw bytes. That reading step is a security boundary. If two programs read the same bytes differently, an attacker can show each one a different certificate. That is not a theory: it is how the 2009 NUL-in-the-name certificates fooled browsers, and how a 2014 bug let forged RSA signatures past Firefox and Chrome. This lab takes the mystery out of the format. You write a decoder for DER, the strict binary encoding certificates use, from nothing but the specification. You prove…

What you'll learn

Steps in this lab

  1. What you are building: a decoder for the bytes under every certificate
  2. Set up: a terminal, Python and OpenSSL
  3. Make two certificates of your own with openssl req -x509
  4. Read the first sixteen bytes by hand: tags and lengths
  5. Write the decoder: der.py, with a strict mode and a lax mode
  6. Value types, proven on hand-made bytes: INTEGER, OID, tags, lengths, times, BIT STRING
  7. Walk your certificate: the tree, then tbsCertificate field by field
  8. Prove it against OpenSSL: every TLV and every field, then the 2050 rule
  9. Run it over the real roots your computer trusts
  10. Strictness as a security property: mutate your own certificate and measure who accepts it
  11. Why parser differentials mattered: two real cases, explained
  12. Honest negatives: what strict parsing does not do, measured
  13. Do it better: never ship this parser, and what a pro does instead

Open the full interactive lab →