<aside> 🧭
Module 09 · Revocation: CRL, OCSP & Why It's Broken
Every module so far has had a note saying "revocation is covered in Module 09". This is it — and the honest headline is that revocation on the public internet does not work, and the industry has stopped pretending otherwise. Understanding why explains the single biggest change happening in TLS right now: certificate lifetimes collapsing from years to weeks.
🧠 concept → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (answers hidden)
Prerequisite: Modules 01–08. You need the CRL and AIA extensions from Module 03 (C5), openssl ca and index.txt from Module 05 (B2), and OCSP stapling from Module 08 (D2).
</aside>
<aside> 💳
The picture to hold in your head for this whole module — a cancelled credit card.
Your card is stolen. You ring the bank and cancel it. The card itself is unchanged — same numbers, same hologram, same expiry date printed on the front. Nothing about the card tells a shopkeeper it is dead.
So how does the shop find out? Two ways, historically:
Both work in principle. Both have a problem that turns out to be fatal in practice — and this module is about what that problem is and what replaced them.
</aside>
<aside> 🖥️
Build the revocation lab. Everything here runs offline — no network, no CA, nothing outside ~/tls-lab/.
mkdir -p ~/tls-lab/m09 && cd ~/tls-lab/m09
umask 077
mkdir -p certs db && touch db/index.txt
openssl rand -hex 8 > db/serial
echo 1000 > db/crlnumber # NEW: CRLs need their own counter
cat > ca.cnf <<'EOF'
[ca]
default_ca=CA
[CA]
dir=.
database=$dir/db/index.txt
serial=$dir/db/serial
crlnumber=$dir/db/crlnumber
new_certs_dir=$dir/certs
certificate=$dir/ca.crt
private_key=$dir/ca.key
default_md=sha256
default_days=90
default_crl_days=7
policy=pol
rand_serial=yes
unique_subject=no
copy_extensions=none
email_in_dn=no
[pol]
commonName=supplied
[srv]
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=serverAuth
subjectAltName=DNS:a.test,DNS:b.test,DNS:c.test
crlDistributionPoints=URI:<http://crl.example.test/ca.crl>
EOF
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ca.key
openssl req -x509 -key ca.key -out ca.crt -days 3650 -subj "/CN=Revocation Lab CA" \
-addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out srv.key
for n in a b c; do
openssl req -new -key srv.key -out $n.csr -subj "/CN=$n.test"
openssl ca -config ca.cnf -extensions srv -batch -notext -in $n.csr -out $n.crt
done
cat db/index.txt
Two new things in this config, both required before openssl ca will generate a CRL: a crlnumber file (a counter, like serial, but for CRLs) and default_crl_days (how long each CRL is valid).
All output in this module was produced on OpenSSL 3.0.13.
</aside>
<aside> 📖
Official docs: RFC 5280 §5 — CRL and CRL Extensions Profile · openssl ca — -revoke and -crl_reason · RFC 5280 §5.3.1 — Reason Code
</aside>
<aside> 📒
The analogy — crossing a name off the ledger.
In Module 05 the CA's index.txt was described as the office ledger: every document issued, with its number and its status.
Revocation is nothing more than changing one letter in that ledger — V for valid becomes R for revoked — and writing today's date beside it.
That is genuinely all it is. Everything else in this module is about the much harder problem of telling the world what the ledger now says.
</aside>
🧪 Exercise A1.1 — Revoke a certificate and watch the ledger change
cd ~/tls-lab/m09
echo "=== the ledger before ==="
cat db/index.txt
echo
echo "=== revoke b.test, and say why ==="
openssl ca -config ca.cnf -revoke b.crt -crl_reason keyCompromise
echo
echo "=== the ledger after ==="
cat db/index.txt
<aside> 📖
Official docs: RFC 5280 §5 — CRL Profile · openssl ca -gencrl · openssl crl manual
</aside>
<aside> 📕
The analogy — the book of stolen card numbers.
Before card machines were online, shops kept a printed booklet of cancelled card numbers under the counter. The bank posted a new one every week. For a large purchase the assistant would look the number up.
It works, and you can see the problems immediately:
A CRL is that booklet: a signed list of revoked serial numbers, published at a URL, with a "next update" date.
</aside>
🧪 Exercise A2.1 — Generate a real CRL and read it