Certificate Chains
X.509 trust paths, hostname matching, revocation.
Certificate Chains
A TLS certificate is a small file that ties a public key to a name. The whole edifice of HTTPS — the reason your browser will trust a server it has never seen before — rests on the chain of signatures linking that file back to a CA your computer already trusts. Break any link and the lock goes red.
Analogy
Think about how you'd verify a notarised document you've never seen before. The document has a notary's stamp; the notary has a commission signed by the county clerk; the county clerk is appointed by the state registrar; and the state registrar is a public office the government itself vouches for. To trust the document you don't need to personally know the notary — you just follow the chain of endorsements up to an authority you already recognise. A TLS certificate chain is exactly this: the leaf certificate for the website is vouched for by an intermediate CA, which is vouched for by a root CA that your operating system ships already trusting. Break any endorsement along the way and the whole chain falls.
What's in a certificate
An X.509 certificate is an ASN.1 structure that roughly contains:
- Subject — who this cert is for (
CN=example.com, plus Subject Alternative Names). - Issuer — who signed it.
- Public key — the key being certified.
- Validity —
notBeforeandnotAftertimestamps. - Key usage — what operations the key is allowed to do (digital signature, key encipherment, cert signing, CRL signing...).
- Extensions — Basic Constraints (
CA:TRUEorCA:FALSE), SANs (the DNS names), AIA (where to fetch OCSP and parents), CT SCTs. - Signature — the issuer's signature over all of the above.
That signature is the whole trust mechanism. The issuer says "yes, I vouch for this subject having this public key, until this date".
Root, intermediate, leaf
A browser trust store ships ~150 root CAs. Roots are self-signed — their subject equals their issuer. They sit offline in an HSM. A root can sign intermediate CAs, each of which can sign more intermediates or leaf certificates. A leaf is what a real server presents.
CN=ISRG Root X1 <- self-signed, in your browser's trust store
└─ CN=R3 <- intermediate, CA:TRUE
└─ CN=example.com <- leaf, CA:FALSE
Servers send everything except the root. The browser already has the root; re-sending it wastes bytes. The browser rebuilds the chain by matching each cert's issuer to the next cert's subject. If no next cert matches and the top issuer isn't a trusted root, validation fails with "unable to get issuer cert".
What validation actually checks
Walk the chain from leaf upward:
- Each cert is within its validity window right now.
- The leaf has
digital-signaturein its key usage, and none ofCA:TRUE. - Every intermediate has
CA:TRUEandkeyCertSignin its key usage. - Each cert's
issuerDN matches the next cert'ssubjectDN. - The signature on each cert verifies against the next cert's public key.
- The topmost issuer is a subject in the trust store.
- The leaf's SAN list covers the hostname you typed.
Miss any of these and the browser shows a warning page. Most TLS errors in the wild are (1) or (7).
Hostname matching, precisely
The leaf's subjectAltName extension carries a list of DNS names. The browser matches the typed hostname against that list. A SAN of example.com matches only example.com. A SAN of *.example.com matches exactly one label deep — www.example.com matches, a.b.example.com does not, and neither does the apex example.com. The CN field is ignored by modern browsers. Firefox and Chrome stopped trusting it in 2017.
Revocation — the weakest part
What happens when a private key leaks and the CA needs to say "never mind"?
- CRLs — the CA publishes a big signed list of revoked serial numbers. Browsers must download it. It is often stale, always big, and frequently skipped.
- OCSP — the browser asks the CA's OCSP responder "is this specific serial still good?". Correct but slow and privacy-leaking (the CA learns which sites you visit). Chrome disables OCSP by default for performance.
- OCSP stapling — the server fetches a fresh signed "still good" response from the CA and bolts it onto the handshake. Fast, privacy-preserving, but requires the server to refresh it periodically.
- CRLite / CRLSets — Mozilla and Chrome respectively push small bloom-filter-style blocklists with browser updates. Catches mass-revocation events; not a per-site mechanism.
In practice, revocation in the WebPKI is best-effort. The community's answer has been to issue short-lived certs (Let's Encrypt: 90 days) so the blast radius of a stolen key is naturally bounded.
Certificate Transparency
Every cert issued by a publicly-trusted CA since 2018 must be logged in an append-only CT log. Browsers refuse certs whose SCTs don't prove they were logged. This means a domain owner can monitor CT logs (via crt.sh or Cert Spotter) to detect any cert issued for their name, by anyone. It killed the "rogue CA" attack overnight — when Symantec was caught misissuing certs in 2015, it was CT logs that caught them.
What to check when a cert goes bad
# Show the chain the server presents
openssl s_client -showcerts -connect example.com:443 -servername example.com </dev/null
# Decode a specific cert
openssl x509 -in cert.pem -noout -text
# Verify a chain against the system trust store
openssl verify -CAfile /etc/ssl/cert.pem -untrusted intermediate.pem leaf.pem
If you see "unable to verify the first certificate" in curl, your server is not sending the intermediate. Fix it — don't ignore the warning.
Why this matters
A misconfigured chain is the most common HTTPS bug in production. Some browsers (Chrome with its bundled CRLSets, Firefox with its Mozilla list) may tolerate missing intermediates on many sites. Mobile apps and older TLS stacks often will not. The only safe fix is to send the full leaf+intermediate chain, every time, from every edge node.