Certificate Transparency and Revocation
A PKI certificate is a signed assertion — “this public key belongs to
example.com” — with a validity window baked in. Two things can go wrong that the signature alone cannot fix, and each has its own machinery. First, a certificate authority (CA) can mis-issue: sign a certificate for a domain it should not have, whether by compromise, error, or a rogue employee. Certificate Transparency (CT) (RFC 6962, 2013) attacks this by forcing every issued certificate into public, append-only, cryptographically-verifiable logs, so mis-issuance is detectable even when it is not preventable. Second, a certificate that was issued correctly may need to be undone before it expires — a leaked private key, a decommissioned server. Revocation — Certificate Revocation Lists (CRL, RFC 5280) and the Online Certificate Status Protocol (OCSP, RFC 6960) — is meant to broadcast “don’t trust this one anymore.” The uncomfortable truth of this note is that revocation is largely broken in practice (browsers “soft-fail” past a failed check), which is why the industry has pivoted to short-lived certificates as the pragmatic answer. This note owns CT and revocation as protocols; the certificate structure and chain-building they operate on are X.509 Certificate Validation and Public Key Infrastructure and Certificate Chains.
Mental Model — Two Different Failures, Two Different Fixes
The single most common confusion here is treating CT and revocation as the same thing. They solve orthogonal problems. CT is about detection of bad issuance: it makes the existence of every certificate public so that a domain owner (or a monitor acting for them) can spot a certificate they never asked for. Revocation is about withdrawal of trust: given a specific certificate you know is bad, tell the world’s clients to stop honouring it. CT does not stop a mis-issued certificate from working; revocation does not tell you a certificate was mis-issued. In the real workflow they chain together — CT surfaces the bad certificate, the CA revokes it, and clients ideally stop trusting it — but each link is a distinct mechanism with distinct failure modes, and the revocation link is the weak one.
flowchart TB subgraph DETECT["Detection — Certificate Transparency (RFC 6962)"] CA1["CA issues a cert<br/>(correct OR mis-issued)"] --> LOG["Public append-only<br/>Merkle-tree CT log"] LOG --> SCT["Log returns an SCT<br/>(promise to include)"] LOG --> MON["Monitors watch logs;<br/>domain owner spots a<br/>cert it never requested"] end subgraph WITHDRAW["Withdrawal — Revocation"] BAD["Cert known to be bad<br/>(leaked key, mis-issued)"] --> CA2["CA publishes revocation"] CA2 --> CRL["CRL: signed list of<br/>revoked serial numbers"] CA2 --> OCSP["OCSP: per-cert<br/>status query"] CRL --> CLIENT["Client SHOULD stop<br/>trusting the cert"] OCSP --> CLIENT CLIENT -. "but soft-fails on<br/>a blocked check" .-> WEAK["Revocation largely<br/>ineffective vs active attacker"] end MON -. "detected bad cert must then be" .-> BAD
How detection and withdrawal chain together. What it shows: CT (top) makes every issuance public and gives monitors a way to notice a bad certificate; revocation (bottom) is the separate step that tries to withdraw trust from a known-bad certificate — and it leaks trust at the last hop, where clients “soft-fail” (proceed anyway) when a revocation check is blocked. The insight to take: CT is robust because its guarantee is cryptographic and offline-verifiable; revocation is fragile because its guarantee depends on the client successfully reaching a network service that an attacker can simply block.
Revocation, Part 1 — Certificate Revocation Lists
The oldest revocation mechanism is the CRL, defined in RFC 5280 §5 as “a time-stamped list identifying revoked certificates that is signed by a CA or CRL issuer and made freely available in a public repository.” Structurally a CRL is a signed CertificateList wrapping a TBSCertList (“to-be-signed certificate list”) whose load-bearing fields are:
thisUpdate— when this CRL was issued.nextUpdate— when the next CRL is expected (so a client knows how stale its copy may be).revokedCertificates— the list itself: for each revoked cert, itsuserCertificate(the serial number), arevocationDate, and optionalcrlEntryExtensions.
Each entry can carry a reason code, and the RFC’s enumerated reasons are worth knowing because they show up in incident reports: keyCompromise, cACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold, and removeFromCRL. A certificate advertises where its CRL lives via the CRL Distribution Points extension, which points at the URL a client should fetch.
The fatal scaling property of CRLs is that they grow without bound and are downloaded in full. A busy CA with millions of certificates accumulates a CRL that can be many megabytes; a client that wants to check one certificate must fetch (or have cached) the entire list, and the “time granularity of revocation is limited to the CRL issue period” — revoke a certificate the moment after a CRL is published and clients won’t learn of it until the next one. Delta CRLs (incremental updates listing only changes since a base CRL) were specified to soften the bandwidth problem but add complexity and never displaced the full-download model in browsers. The upshot is that browsers historically stopped fetching CRLs on the fast path entirely.
Revocation, Part 2 — OCSP and Stapling
The Online Certificate Status Protocol (RFC 6960) was the answer to “downloading a whole CRL to check one certificate is absurd.” Instead of a list, OCSP is a point query: the client asks a responder “is this one certificate revoked?” and gets a small, signed answer. The certificate to ask about is named by a CertID — hashAlgorithm, issuerNameHash (hash of the issuer’s distinguished name), issuerKeyHash (hash of the issuer’s public key), and serialNumber — the dual issuer hashes disambiguating CAs that share a name. The response is a BasicOCSPResponse whose CertStatus is one of three values:
good— no revoked certificate with that serial is currently within its validity interval.revoked— carries arevocationTimeand an optionalrevocationReason(and can even flag certificates that were never issued).unknown— the responder has no information.
Timing fields thisUpdate, nextUpdate, and producedAt bound freshness, and an optional nonce extension (id-pkix-ocsp-nonce) “cryptographically binds a request and a response to prevent replay attacks.” The response is signed either by the issuing CA directly or by a delegated Authorized Responder whose certificate carries the id-kp-OCSPSigning extended-key-usage (EKU).
OCSP fixed the bandwidth problem but introduced two new ones. Latency: the client now makes an extra network request — to a third party — in the critical path of every new connection, often to a responder on a different, slower network than the site itself. Privacy: the OCSP responder, operated by the CA, “immediately becomes aware of which website is being visited from that visitor’s particular IP address” (Let’s Encrypt) — a per-request leak of the user’s browsing to a third party.
OCSP stapling (RFC 6066 §8, the status_request extension) was designed to fix both. The client sends a status_request extension in its ClientHello; the server — not the client — fetches a fresh OCSP response for its own certificate ahead of time and staples it into the handshake as a CertificateStatus message, right after its Certificate. Because the server does the fetching, the client makes no extra round trip and the OCSP responder never sees the client’s IP — it only ever talks to the server. Stapling is strictly better than client-side OCSP, but it is optional: a server that does not staple simply omits the CertificateStatus message, and the client cannot tell “this server chose not to staple” from “an attacker stripped the staple.”
That gap is closed by Must-Staple — the “TLS Feature” extension of RFC 7633 (OID id-pe-tlsfeature). A CA can embed status_request (value 5) into the certificate itself, which commits the server to always staple: “a client MUST treat a certificate with a TLS feature extension as an invalid certificate if the features offered by the server do not contain all features present in … the TLS feature extension.” Now the absence of a staple is a hard failure, so an attacker can no longer strip it. Must-Staple turns the soft-fail into a hard-fail — but only for certificates that opt in, and adoption stayed low.
Why Revocation Is “Broken” — Soft-Fail
The reason none of the above added up to working revocation is captured in Adam Langley’s blunt 2014 essay “No, don’t enable revocation checking”: online revocation checking “doesn’t work and you are no more secure by switching it on” (ImperialViolet). The argument is about the threat model. Revocation exists to protect you from an active man-in-the-middle wielding a certificate that should not be trusted (a stolen key, a mis-issued cert). But browsers implement soft-fail: if the revocation check — CRL fetch or OCSP query — times out, is blocked, or errors, the browser proceeds and accepts the certificate anyway. And here is the killer: an attacker who can man-in-the-middle your traffic to present the bad certificate “can intercept all your traffic, including OCSP traffic. Thus they can block OCSP lookups and soft-fail behaviour means that a revoked certificate will be accepted.” The very adversary revocation is meant to stop is the one best placed to defeat it. As Langley puts it, “if they can’t even intercept the traffic then you didn’t need any authentication to protect it from them in the first place.”
Why not hard-fail (reject the certificate if the check fails)? Because it makes the revocation infrastructure a single point of failure for the whole web: “if everyone did hard-fail then taking down an OCSP service would be sufficient to take down lots of Internet sites.” A responder outage — or an attacker DoSing it — would break every site whose certificate depends on it. Faced with soft-fail-is-useless and hard-fail-is-catastrophic, Chrome disabled online revocation checks and instead ships CRLSets: “we compile daily lists of some high-value revocations and use Chrome’s auto-update mechanism to push them to Chrome installations.” Firefox built the analogous CRLite (a compressed, Bloom-filter-based aggregate of all known revocations pushed to the browser). Both move revocation off the connection critical path and into the browser’s update channel, where an attacker cannot block it per-connection.
Uncertain
Verify: the current live status and exact mechanics of Chrome CRLSets and Firefox CRLite (coverage, update cadence) as of mid-2026, and whether Safari/Apple’s on-device revocation aggregation behaves the same way. Reason: the CRLSet claim is grounded in Langley’s 2014 essay and browser-vendor behaviour decays; I did not fetch a 2025–2026 primary description of either system. To resolve: consult current Chromium
net/docsand Mozilla’s CRLite documentation.#uncertain
The Pragmatic Answer — Short-Lived Certificates
If you cannot reliably revoke a certificate, the alternative is to make certificates expire so quickly that revocation barely matters — a compromised certificate is only dangerous for the few days until it lapses on its own. This is now the industry’s explicit direction, visible in two concrete 2024–2025 moves. Let’s Encrypt is retiring OCSP entirely: it stopped honouring new OCSP Must-Staple requests on 30 January 2025, dropped OCSP URLs from newly-issued certificates on 7 May 2025, and shut down its OCSP responders on 6 August 2025, moving to CRLs only — justified primarily by the OCSP privacy leak and the operational burden, since “operating OCSP services has taken up considerable resources” (Let’s Encrypt). In parallel, Let’s Encrypt began offering 6-day certificates, short enough that revocation is almost moot within their lifetime.
The whole ecosystem is following: the CA/Browser Forum passed Ballot SC-081v3 (proposed by Apple’s Clint Wilson, adopted 11 April 2025), which schedules a stepped reduction of the maximum certificate validity period from today’s 398 days down to 47 days, “starting in March 2026 and concluding in March 2029” (CA/Browser Forum). Shorter lifetimes force automation (you cannot renew a 47-day cert by hand at scale), and automation is what makes the whole model work — it is no coincidence that Let’s Encrypt’s ACME automation and the lifetime reductions arrive together.
Uncertain
Verify: the exact intermediate steps and effective dates of the SC-081v3 schedule (widely reported as ~200 days from 15 March 2026, ~100 days from 15 March 2027, and 47 days from 15 March 2029, with parallel data-reuse cuts). Reason: the CA/Browser Forum ballot page did not render the step table when fetched, and the specific day counts and dates above come from secondary coverage, not the primary ballot text. To resolve: read the SC-081v3 redline in the CA/Browser Forum Baseline Requirements.
#uncertain
Certificate Transparency — Making Issuance Public
Certificate Transparency (RFC 6962) tackles the other failure — a CA issuing a certificate it should not have. Its design principle is that mis-issuance cannot always be prevented, but it can be made detectable by requiring every certificate to be recorded in “publicly auditable, append-only, untrusted logs of all issued certificates.”
The cryptographic core is the Merkle Hash Tree. A CT log is an ever-growing binary tree of SHA-256 hashes: each certificate is a leaf, and each internal node hashes its two children, up to a single root hash that commits to the entire contents of the log. The recursive Merkle Tree Hash (MTH) is defined so that a leaf is SHA-256(0x00 || leaf_data) and an internal node over a list D[n] (with k the largest power of two below n) is SHA-256(0x01 || MTH(D[0:k]) || MTH(D[k:n])) — the domain-separating 0x00/0x01 prefixes preventing a leaf from being confused with an internal node. This structure gives two efficient proofs. A Merkle audit path (inclusion proof) is the short list of sibling hashes needed to recompute the root from one leaf — proof that a specific certificate really is in the log. A Merkle consistency proof shows that one published root is a prefix extension of an earlier one — proof that the log only ever appended and never rewrote or deleted history. The log periodically signs a Signed Tree Head (STH) over its current size, timestamp, and root hash; a monitor that keeps STHs and checks consistency proofs between them can detect a log that tries to fork or tamper with its history.
The client-facing artefact is the Signed Certificate Timestamp (SCT) — “the log’s promise to incorporate the certificate in the Merkle Tree within a fixed amount of time known as the Maximum Merge Delay (MMD).” When a CA submits a certificate, the log immediately returns an SCT (a signed statement “I received this at time T and will merge it within the MMD”), before actually incorporating it, so issuance need not block on the merge. A TLS client can be given SCTs three ways (RFC 6962 requires clients to support all three, servers at least one):
- Embedded in the certificate as an X.509v3 extension (OID
1.3.6.1.4.1.11129.2.4.2) — the CA obtains SCTs at issuance and bakes them in, so nothing extra is needed at handshake time. This is by far the most common. - A TLS extension (
signed_certificate_timestamp) sent during the handshake. - In a stapled OCSP response (OID
1.3.6.1.4.1.11129.2.4.5).
Embedding creates a chicken-and-egg problem — the SCT must be inside the certificate, but you cannot log a certificate that does not exist yet — solved by the precertificate. The CA builds a precertificate identical to the real one but with a special critical poison extension (OID 1.3.6.1.4.1.11129.2.4.3) that makes it fail normal validation, submits that to logs, collects the SCTs, and embeds them in the final certificate. The log binds its SCT to the poisoned TBSCertificate, tying the CA’s issuance intent to the logged entry.
The ecosystem has three watchdog roles: Submitters feed certificates to logs; Monitors “watch logs and check that they behave correctly” — fetching all entries, verifying signatures and consistency, and, crucially for domain owners, alerting when a certificate appears for a domain the owner never requested; and Auditors verify that the partial view a client sees is consistent with the global log (checking audit and consistency proofs). Services like Certstream and crt.sh let anyone watch the logs in near-real-time.
CT Enforcement and a Real Catch
CT only bites because browsers require it. Chrome’s CT policy states that “all publicly-trusted TLS certificates are required to be CT Compliant to successfully validate”, and a non-compliant certificate “will simply fail to validate” (Chrome CT Policy). Compliance is quantified: for embedded SCTs, a certificate with lifetime ≤180 days needs at least 2 SCTs from distinct logs, and one with a longer lifetime needs 3; in all cases at least two SCTs must come from distinct CT log operators (so no single log operator can unilaterally vouch for a certificate), and at least one must be from a log in a Qualified, Usable, or ReadOnly state. Chrome began enforcing CT for all newly-issued publicly-trusted certificates on 30 April 2018 (with Chrome 68), extending a requirement that had applied to Extended Validation certificates since 2015.
Uncertain
Verify: the 30 April 2018 / Chrome 68 enforcement date. Reason: the current Chrome CT policy page I fetched describes present compliance rules but does not state the historical enforcement date, which I took from secondary coverage. To resolve: confirm against the original Chromium
ct-policyannouncement.#uncertain
CT’s value is not theoretical. In 2015 a Symantec certificate for google.com (an unauthorised Extended Validation certificate, issued during internal testing and valid for only a day) was caught through Certificate Transparency — the first high-profile mis-issuance surfaced by CT rather than by accident. Follow-up analysis of CT logs by Andrew Ayer of SSLMate uncovered scores more unauthorised Symantec-family certificates (for example.com, test.com, and others), and the incident escalated into Google requiring all Symantec certificates to be CT-logged from June 2016 and, ultimately, the distrust of Symantec’s CA business — a chain of events that began with a certificate appearing in a public log that never should have existed.
Uncertain
Verify: the specifics of the 2015 Symantec google.com incident (one-day validity, “internal testing”, SSLMate/Andrew Ayer’s role, the count of follow-on certificates). Reason: these facts come from aggregated secondary reporting (EFF, SecurityWeek, mailing-list threads surfaced via web search), not a primary incident report I fetched in full. To resolve: read the EFF write-up and the Mozilla
dev-security-policythread directly.#uncertain
How CT and Revocation Fit Together
The two mechanisms are complementary halves of “keeping the CA honest.” CT is the detection layer and it is strong: its guarantees are cryptographic (Merkle proofs) and verifiable offline, an attacker cannot block a per-connection check to defeat it, and enforcement is a simple local rule (does this certificate carry enough valid SCTs?). Revocation is the response layer and it is weak: when CT surfaces a mis-issued certificate, the correct response is to revoke it — but soft-fail means clients may keep trusting it anyway. This asymmetry is exactly why the industry leans on short lifetimes as the backstop: a mis-issued certificate that CT catches will expire on its own within days, limiting the damage window even if revocation never reaches every client. Detection you can trust plus a short fuse beats a revocation broadcast you cannot rely on.
Failure Modes and Common Misunderstandings
“CT prevents mis-issuance.” No — CT makes mis-issuance detectable, not impossible. A CA can still issue a bad certificate; CT ensures it cannot do so secretly, because the certificate must be logged (with enough SCTs) or browsers reject it. The deterrent is publicity, not prevention.
“An SCT proves the certificate is in the log.” Not quite — an SCT is a promise to include the certificate within the Maximum Merge Delay, not proof of present inclusion. Verifying actual inclusion requires an audit path against a later STH, which auditors, not typical TLS clients, perform.
“Revocation protects me from a stolen certificate.” Against a passive observer, maybe; against the active attacker who actually wields the stolen certificate, largely not, because that attacker can block your revocation check and soft-fail lets the connection through. This is the core of Langley’s argument.
“OCSP stapling leaks my browsing to the CA.” The opposite — client-side OCSP leaks it; stapling is what fixes the leak, because the server fetches the response and the responder never sees the client. The privacy problem Let’s Encrypt cites is with un-stapled, client-driven OCSP.
“Must-Staple is on by default.” No — it is a per-certificate opt-in extension, and with Let’s Encrypt retiring OCSP it is being actively wound down. Do not assume the absence of a staple is an error unless the certificate carries the TLS Feature extension.
Confusing CT logs with CRLs. A CT log is an append-only record of issued certificates (detection of issuance); a CRL is a list of revoked certificates (withdrawal of trust). They move in opposite directions and are not substitutes.
See Also
- Public Key Infrastructure and Certificate Chains — the CA hierarchy, roots, and chain-building that CT audits and revocation withdraws from
- X.509 Certificate Validation — path validation, where SCT-checking and (historically) revocation-checking plug in as steps
- The TLS 1.3 Handshake — where the certificate, stapled OCSP response, and embedded SCTs are actually delivered on the wire
- TLS Session Resumption and 0-RTT — the sibling trust-machinery note; short certificate lifetimes and resumption-ticket lifetimes are related freshness knobs
- Transport Layer Security Fundamentals — the authenticity guarantee that certificates, CT, and revocation all serve
- Mutual TLS — client certificates face the same revocation and transparency questions from the other side
- MOC: Networking and Protocols MOC — §5 Transport Security