51 min read

A Perfect Signature for a Certificate That Should Never Have Existed: A Field Guide to X.509 and PKI

How the Web PKI turns a certificate into a trust decision -- path validation, revocation, and Certificate Transparency -- and every famous way that trust broke.

Permalink

1. The Certificate That Should Not Have Existed

In the late summer of 2011, hundreds of thousands of people in Iran opened Gmail over what looked like a perfectly secure connection. The padlock was closed. The certificate for *.google.com chained to a trusted root. Every signature in that chain verified flawlessly. It was also completely fake: minted by a breached Dutch certificate authority called DigiNotar, it let someone read all of that traffic, and nothing in any browser's validation logic so much as blinked [1]. The RSA math was perfect. The trust was the bug.

Sit with the paradox, because the rest of this article lives inside it. A certificate that is cryptographically perfect and a total compromise at the same time is not a contradiction the mathematics can resolve. Modular exponentiation did what it promised; SHA hashed what it was given; the signature over the certificate was valid in the strict, checkable sense that it matched the issuer's public key. And a browser trusting that certificate handed an eavesdropper a live feed of people's email.

Here is the reframing that dissolves it. A certificate is not identity, and it is not magic. It is a signed statement: one party vouches, by signature, that a particular public key belongs to a particular name. "Verifying" a certificate means checking that signature -- the easy, automatable part. Deciding whether to believe the statement it signs is the hard part, and no signature check can do it for you.

At DigiNotar, the statement was a lie, signed by an authority the whole Web had agreed to trust. The variable was never the cryptography. It was delegation -- whom a trusted authority chose to vouch for.

That gives us the single diagnostic tool this field guide is built around, a sentence to ask of any trust system you will ever design or debug:

Whom am I trusting, to say what, and how would I know if they lied?

By the end of this article you will drop any PKI disaster into one of those buckets on sight. DigiNotar is a whom did I trust failure -- the answer turned out to be an attacker. Flame, a year later, forged a Microsoft code-signing certificate with a novel hash collision, a what were they allowed to say failure reaching into a corner of Microsoft's own PKI [2]. Debian's OpenSSL, in 2008, generated certificates that were structurally flawless and yet trivially guessable [3]. None of them broke a cipher. Every one of them broke a delegation.

This is Part 4 of a field guide for protocol designers, and it assumes the earlier parts' habits of mind. DigiNotar is, in the language of Part 1, a wrong-adversary-model story: path validation was secure against exactly the attacker it was never going to face. Debian belongs to Part 2's account of what a weak key is. And the parsing bugs we will meet in the enforcement code are Part 3's serialization hazards wearing certificates.

If neither RSA's modular exponentiation nor SHA's collision resistance was broken at DigiNotar, then what, exactly, failed? To answer that with any precision, you first have to know what a certificate actually is -- and what a signature over one does, and does not, promise.

2. What an X.509 Certificate Actually Is

Strip away the mystique and an X.509 certificate is a small, rigidly-encoded data structure in which one key vouches, by signature, for a binding between another key and a name, plus a set of machine-readable limits on what that key may do.

X.509 certificate

A signed data structure that binds a public key to a name (and to a set of usage constraints), so that anyone holding the issuer's public key can verify the binding offline. Its format is defined by ITU-T Recommendation X.509 and profiled for the Internet by RFC 5280.

The signed part of the certificate is called the tbsCertificate -- "to be signed." RFC 5280 fixes its fields: a version number, a serial number, the issuer's name, a validity window (notBefore and notAfter), the subject's name, the subject's public key (subjectPublicKeyInfo), and, since version 3, a list of extensions [4]. The issuer then hashes that whole body and signs the hash. The certificate you receive on the wire is the body plus that one signature.

Ctrl + scroll to zoom
An X.509 certificate is a to-be-signed body plus one signature over it. Verification hashes the body and checks the signature against the issuer's public key.

What does verifying that signature actually establish? Almost exactly one thing. Let HH be the hash function and σ\sigma the signature; a relying party recomputes H(tbsCertificate)H(\text{tbsCertificate}), runs the signature-verification algorithm against the issuer's public key pkpk, and confirms the clock is inside the window:

Verify(pk,H(tbsCertificate),σ)=1andtnotBeforetnowtnotAfter.\text{Verify}(pk,\, H(\text{tbsCertificate}),\, \sigma) = 1 \quad\text{and}\quad t_{\text{notBefore}} \le t_{\text{now}} \le t_{\text{notAfter}}.

That is an O(1)O(1) operation over a single certificate -- one hash, one signature check, two date comparisons. A student can implement it in an afternoon. The cost of verifying one certificate does not grow with anything: it is a fixed number of operations regardless of how many certificates exist in the world. The hard part of PKI is never this check. It is deciding whether to believe the statement the check confirms was signed.

This is the load-bearing observation of the whole field, worth stating flatly: the signature check is the easy, automatable part, and deciding whether to believe the signed statement is the hard, unautomatable part. A valid signature tells you that whoever holds the issuer's private key asserted this binding. It tells you nothing about whether that assertion is true, or whether that issuer should have been trusted to make it. DigiNotar's forged certificate passed the check perfectly.

The bytes themselves are encoded with ASN.1 using the Distinguished Encoding Rules.

ASN.1 and Distinguished Encoding Rules (DER)

ASN.1 is a language for describing structured data; DER is a canonical binary encoding of it in which every value has exactly one valid byte representation. X.509 certificates are DER-encoded so that the signature covers a single, unambiguous sequence of bytes.

That canonical-encoding requirement is not pedantry. If two different byte sequences could parse to the "same" certificate, an attacker could sign one and present another, and the whole scheme unravels -- which is why certificate parsers are a recurring attack surface, a hazard Part 3 treats in depth [5].

The format grew in three steps. Version 1 (1988) carried only the basic fields; version 2 added issuer and subject unique identifiers; version 3 (1996) added the extension mechanism -- a list of {OID, critical flag, value} entries that finally let a certificate carry its own authorization scope [4]. That extension seam is where the "trusted to say what" question gets its answer, and where a two-decade family of enforcement bugs would later live.

So a certificate is just a signed claim, verifiable offline by anyone holding the issuer's key. That idea raises the question the next forty years of engineering tried to answer: where did it come from, and why did it take so long to make it work on the open Internet?

3. Where the Idea Came From: The Trust Gap in Public-Key Cryptography

Public-key cryptography did not create trust. It created a gap. When Whitfield Diffie and Martin Hellman published "New Directions in Cryptography" in 1976, they removed the need for two parties to share a secret before they could communicate securely. But their own paper leaned on a trustworthy "Public File" -- a directory you would query to learn someone's public key [6]. Knowing that a key really belongs to the party you think it does was, and remains, a trust problem, not a math problem.

Querying a live directory for every correspondent was a bottleneck and a hazard: the directory was online, central, and had to be trusted in real time. Two years later, an MIT undergraduate named Loren Kohnfelder proposed the fix in his 1978 bachelor's thesis. Replace the live lookup with a signed object -- a certificate -- that anyone can verify offline by checking one signature [7]. That single move, from an online lookup to an offline signed token, is the germ of every certificate authority that has existed since.

Ctrl + scroll to zoom
The trust-model genealogy, 1976 to 2026: each era answers a failure of the one before it.

The concept needed a standard, and in 1988 the CCITT (renamed the ITU-T in 1993) published X.509 as the authentication layer of the X.500 directory series. That parentage is the format's original sin. X.500 envisioned one global directory with one global namespace, and X.509 inherited both assumptions [8]. The global directory was never built. The format outlived it, carrying forward a picture of the world -- one namespace, one hierarchy -- that the messy, multi-vendor Internet would spend decades constraining.

The edition years (v1 in 1988, v3 in 1996) are corroborated here through the normative references of RFC 5280 rather than read from the ITU text directly -- and it is RFC 5280 that carries the profile browsers actually implement [4].

The 1990s taught two hard lessons about how many authorities the Web should trust. The first attempt, Privacy-Enhanced Mail, specified a single global certification hierarchy: one root, the Internet Policy Registration Authority, atop everything [9]. It was undeployable. No one could agree on who should hold the one root key, and the model died. The opposite approach won by shipping. When Netscape put X.509 certificates under its new Secure Sockets Layer protocol, it bundled many independent root certificates into the browser itself, and the commercial certificate authority industry -- and the browser root store -- was born [10]. Taher Elgamal, Netscape's chief scientist, is often called the "father of SSL," and he did lead the effort. But SSL 3.0, the version that survived, was substantially redesigned with Paul Kocher and Phil Karlton, and SSL 1.0 never shipped publicly [10]. Treat the epithet as an honorific, not a claim of sole authorship.

That left a standards problem: raw X.509 was too permissive for the open Web. The IETF's PKIX working group produced a constrained Internet profile, first as RFC 2459 in 1999 and then as the RFC 5280 that still governs Web certificates today [11]. PKIX also did something subtle the next section depends on: it separated the messy job of finding a chain of certificates from the precise job of checking one.

Other trust models were proposed and lost. PGP's web of trust asked users to vouch for each other's keys directly, but it foundered on usability [12, 13]. SPKI/SDSI tried authorization without global names and never saw adoption [14]. DANE later offered to anchor certificate trust in DNSSEC instead, a parallel path browsers never shipped [15].

By the 2000s the machinery worked at Internet scale -- hundreds of roots, automatic chaining, a padlock in every browser. And then, one break at a time, the Web discovered that a certificate whose signature verifies is not the same as a certificate you should trust. To see why every one of those breaks is the same kind of break, you need a single lens.

4. The Three Questions of Delegated Trust

Here is the entire article in one sentence, and the tool you will apply to every mechanism below and to tomorrow's certificate CVE: whom am I trusting, to say what, and how would I know if they lied?

Those clauses are not rhetorical. Each names a question that any public-key infrastructure has to answer, each maps to a specific mechanism in X.509, and each has its own catalog of real-world breaks. The sentence names three questions outright, and answering the last one honestly forces a fourth into the open.

Ctrl + scroll to zoom
The diagnostic sentence splits into four questions of delegated trust. Every mechanism and every named break in this article maps to exactly one branch.

Binding is the "whom am I trusting" question: is this key really that name? It lives in issuance, in chain building, and in path validation, and it fails when a certificate is forged, collided, guessable, or signed by an authority that should not have signed it. Authorization is the "to say what" question: even granting that this key is that name, was that name trusted to make this particular claim? It lives in the version-3 extensions and fails when a relying party skips or mis-parses them.

Withdrawal is the question everyone assumes is solved: once you know a certificate is bad, how do you stop trusting it? It lives in revocation, and it has almost never worked. Detection, the fourth question, is the one the field arrived at last and reluctantly: if you cannot prevent a trusted authority from lying, how would you even find out that it did?

QuestionWhat it asksThe X.509 mechanismNamed breaks
BindingIs this key really that name?Issuance, path building, path validationDigiNotar, Flame, Debian, CurveBall
AuthorizationTrusted to say what?Basic Constraints, Key Usage, EKU, Name ConstraintsMS02-050, CVE-2021-3450, Spooky SSL
WithdrawalHow do I stop trusting them?CRL, OCSP, stapling, Must-Staplesoft-fail, Heartbleed CRL costs
DetectionHow would I know if they lied?Certificate Transparency logs and SCTsthe answer, not a break

Every X.509 and PKI failure lands in one of these four questions, and never in the signature or hash math underneath. When you meet a new certificate incident, do not ask "which algorithm broke?" Ask: whom did someone trust, to say what, could anyone take it back, and would anyone have known? The answer is always in the delegation, not the arithmetic.

Start with the first question -- is this key really that name? -- because before a relying party can enforce anything at all, it has to turn a pile of certificates into a single chain it is willing to trust. That turns out to be two very different jobs, and the industry keeps confusing them for one.

5. Binding, Part One: Chain Building Is Not Path Validation

A browser is handed a leaf certificate and a bag of intermediates. Getting from there to "trusted" is not one algorithm but two, and treating them as one is a source of bugs.

Trust anchor and root store

A trust anchor is a certificate authority public key that a relying party trusts a priori -- there is no certificate above it to check. The root store is the curated set of trust anchors that a browser or operating-system root program ships and maintains.

The first job is discovery. Because certificate authorities cross-certify each other, reissue intermediates, and publish "Authority Information Access" pointers to their issuers, the certificates in the wild form a graph with multiple edges and even cycles. Finding a route from your leaf to some trust anchor is a search over that graph.

Path building (RFC 4158)

The graph search that discovers a candidate chain from a leaf certificate up to some trust anchor, navigating cross-certificates, reissued intermediates, and Authority Information Access pointers. On an adversarial cross-certified graph it is worst-case exponential, which is why RFC 4158 is essentially a catalog of pruning heuristics.

Path validation (RFC 5280 Section 6)

The linear state machine that checks one chosen chain: it verifies each signature, checks each validity window, and enforces the authorization extensions (Basic Constraints, Key Usage, Extended Key Usage, Name Constraints, and policy) down the path. A critical extension the verifier does not understand must cause rejection.

Validation is a single pass, so its cost is O(n)O(n) in the chain length nn: for each certificate, check the signature against the next issuer up, confirm the dates, and update the running authorization state from the extensions [4]. The rule that trips up naive implementations is the last one in the definition: if a certificate marks an extension critical and the verifier does not recognize it, the verifier must reject rather than ignore it. Silence is not consent.

Ctrl + scroll to zoom
Two distinct algorithms. Building is a graph search that finds a candidate chain; validation is a linear pass that decides whether that chain is well-formed and authorized.

Keeping the two apart matters because they fail differently. Building can blow up on a pathological cross-certified graph -- worst-case exponential search -- but a slow build is a denial-of-service risk, not a trust breach. Validation is where trust is decided, and its limits are the subject of the rest of this article.

Here is the first and deepest of them, the observation that seeds every failure to come: path validation can prove a chain is well-formed; it can never prove the issuing authority was honest. Everything RFC 5280 Section 6 checks is a property of the certificates. None of it is a property of the decision to sign them.

To make the difference between "verifies" and "authorizes" concrete, here is a certificate as a decoded object, with a few lines that print what it actually permits. Notice that nothing here checks a signature -- it reads the claims.

JavaScript Read a certificate and print what it authorizes
// A decoded X.509 certificate as a plain object. No crypto library needed:
// verifying the signature is easy. Reading what it CLAIMS is the point.
var cert = {
subject: "CN=example.com",
issuer: "CN=Example Root CA",
notBefore: "2026-01-01",
notAfter: "2026-01-07",
basicConstraints: { cA: false },
extendedKeyUsage: ["serverAuth"],
subjectAltName: ["example.com", "www.example.com"]
};

function describeAuthorization(c) {
console.log("Subject: " + c.subject);
console.log("Issued by: " + c.issuer);
console.log("Valid: " + c.notBefore + " through " + c.notAfter);
console.log(c.basicConstraints.cA
  ? "CA flag TRUE: this key MAY sign other certificates."
  : "CA flag false: this key may NOT sign other certificates.");
var purposes = {
  serverAuth: "authenticate a TLS server",
  clientAuth: "authenticate a TLS client",
  codeSigning: "sign executable code",
  emailProtection: "sign or encrypt email"
};
var allowed = (c.extendedKeyUsage || []).map(function (k) {
  return purposes[k] || k;
});
console.log("This certificate authorizes: " + allowed.join(", "));
console.log("For the names: " + c.subjectAltName.join(", "));
}

describeAuthorization(cert);

Press Run to execute.

The binding model got to this point in six recognizable steps, each answering a limitation of the one before:

ApproachYearKey ideaStrengthWhy it was superseded or limited
Online public-key directory1976Live name-to-key lookupDistributes public keys at allOnline single point of failure; no offline authenticity
X.509 v1/v2 certificate1988Signed offline name-to-key tokenPortable, verifiable offlineNo authorization scope; X.500 global namespace
X.509 v3 certificate1996Extensions carry authorization scopeStill the live formatOnly as good as the verifier's enforcement
Path building2005Graph search from leaf to a rootFinds a path amid cross-certs and AIAAmbiguity is a bug class; worst-case exponential
Path validation2008 (RFC 5280; algorithm since RFC 2459, 1999)Section 6 state machine over one chainDeterministic, fully specified checksCannot detect a dishonest CA
Web PKI (many roots)1994Any-root chaining, browser root storeDeployed at Internet scaleTrust equals the trust of the weakest CA

Validation answers "is this chain well-formed?" But well-formed for what? A chain can be flawless and still end in a leaf certificate quietly claiming the right to sign for the entire Internet. That is the second question -- trusted to say what? -- and it has its own two-decade catalog of enforcement bugs.

6. Binding, Part Two: Trusted to Say What?

Version 3's extensions finally let a certificate carry its own limits. Four of them do the heavy lifting for authorization, and each is a field that path validation is supposed to enforce as it walks the chain [4].

Basic Constraints

The extension that says whether a certificate's key may act as a certificate authority (cA = TRUE or FALSE) and, if so, how many sub-CAs may appear below it (pathLenConstraint). A leaf certificate has cA = FALSE and must not be able to sign other certificates.

Extended Key Usage (EKU)

The machine-readable list of purposes a key is permitted to serve -- TLS server authentication, TLS client authentication, code signing, email protection, and so on. A certificate valid for serverAuth is not thereby valid for codeSigning.

Name Constraints

The extension that limits a sub-CA to issuing only within permitted name subtrees (and outside excluded ones). During validation the permitted and excluded sets are intersected down the path, so a constrained sub-CA cannot widen its own authority.

Key Usage is the fourth: a lower-level bitfield (digital signature, key encipherment, certificate signing) that further narrows what the key may do. Together these fields answer the "trusted to say what" question in a form a machine can check. And here is the catch, the sentence that generates a two-decade bug family: a declarative authorization field is worthless if the relying party's code skips, misorders, or mis-parses the check. The certificate can be flawless. If the verifier does not enforce the limit, the limit does not exist.

The archetype is MS02-050, disclosed in 2002. Microsoft's CryptoAPI simply did not check the cA flag in Basic Constraints, so any valid leaf certificate could sign certificates for other names, and every Microsoft application that used CryptoAPI would accept them [17]. Moxie Marlinspike weaponized it in a tool called sslsniff: obtain an ordinary certificate for a domain you control, then use it to mint a certificate for any other domain, and Internet Explorer would trust it [18]. The certificate authority had done nothing wrong. The verifier had.

You might expect that lesson to stay learned. It did not. In March 2021, OpenSSL CVE-2021-3450 landed: a regression in strict mode meant the library would accept a non-CA certificate as a CA -- the exact same bug class, nineteen years later, in the most widely used TLS library on Earth [19].

The failure family is structural, not incidental. Enforcement code is written by humans, and the check that a certificate is not allowed to do something is precisely the check that is easy to forget. Apple's 2014 "goto fail" bug made the same point in a single line -- a duplicated goto statement that skipped the signature check altogether [20]. CurveBall (CVE-2020-0601, 2020) is a cousin worth knowing: Windows CryptoAPI accepted attacker-supplied explicit elliptic-curve parameters, so a signature could verify against an attacker-chosen curve rather than the standard one. The signature was "valid," but the validity was meaningless -- a binding-adjacent verification bug in the same spirit as skipping Basic Constraints [21].

The machinery meant to enforce these limits can itself become the attack surface. In 2022, "Spooky SSL" (CVE-2022-3602 and CVE-2022-3786) was a stack buffer overflow reached during Name-Constraint checking of punycode-encoded email addresses in OpenSSL 3.0 [22]. The code enforcing an authorization limit had a memory-safety bug in its parser -- exactly the serialization hazard Part 3 warns about, now living inside the authorization check itself [23].

To feel how thin the line is, here are two validators over the same forged chain. They differ by one if statement.

JavaScript The Basic Constraints bug: one if-statement apart
// A leaf certificate (cA:false) is trying to sign a certificate for a bank.
var attackerLeaf = { subject: "CN=mallory.example", basicConstraints: { cA: false } };
var forged = { subject: "CN=login.yourbank.com", issuedBy: attackerLeaf };

function accepts(issuer, opts) {
var signatureMatches = true; // assume the crypto checks out -- it usually does
if (opts.checkBasicConstraints && issuer.basicConstraints.cA !== true) {
  return false; // issuer is not a CA, so reject. This is the whole defense.
}
return signatureMatches;
}

console.log("Strict validator (checks cA): " +
(accepts(forged.issuedBy, { checkBasicConstraints: true }) ? "ACCEPT" : "REJECT"));
console.log("Lax validator (skips cA):     " +
(accepts(forged.issuedBy, { checkBasicConstraints: false }) ? "ACCEPT" : "REJECT"));
console.log("The lax path just let a leaf sign for " + forged.subject + ".");

Press Run to execute.

Every one of these breaks had a fix and a lesson, and the Web learned them. But they share a comforting property: the certificate authority was honest, and the code was wrong. What happens when the code is right, the signature verifies, and the authority itself is the adversary?

7. The Binding Failure Catalog: When the Authority Vouched for the Wrong Key

There are three ways a certificate can be perfectly valid and perfectly compromised, and none of them is a bug in the mathematics. Each is a failure of binding -- the "is this key really that name?" question -- and each taught the Web something it did not want to learn.

DigiNotar (2011) is the pure case. Attackers who had breached the Dutch certificate authority used its fully trusted key to issue a valid *.google.com certificate, along with more than 500 others, and someone used the Google certificate to intercept the traffic of roughly 300,000 users in Iran [1]. Every signature verified. Path validation flagged nothing, because a trusted authority had chosen to sign. The forensic report, aptly titled "Black Tulip," traced the intrusion; the company, owned by VASCO, was distrusted by every major browser and declared bankruptcy in September 2011 [24].

DigiNotar has no cryptographic tell. There was nothing in the certificate, the chain, or the signature for path validation to catch, because the failure was not in any of them -- it was in the decision to sign. Prevention failed at the root of trust itself. When a trusted authority turns adversary, the only defense left is detection: making the lie visible after the fact. Hold that thought; it is the reason Certificate Transparency exists.

Flame (2012) made the same point on a different trust path. The Flame espionage platform carried a certificate that chained to Microsoft and appeared valid for code signing, letting its components masquerade as legitimate Windows Update content. The certificate was forged using a novel chosen-prefix MD5 collision -- a new variant, distinct from the 2008 technique -- against a corner of Microsoft's Terminal Server Licensing infrastructure still signing with MD5 [2].

Marc Stevens' "counter-cryptanalysis" later reconstructed it forensically. A hash-function weakness, reached through a forgotten sub-CA, subverted code-signing trust at nation-state scale; the trust path Flame abused is the subject of this companion post. A chosen-prefix collision takes two attacker-chosen prefixes and appends carefully computed bytes so their MD5 digests come out identical. The attacker gets a benign-looking certificate signed and transplants the signature onto a malicious one with the same digest. The underlying "valid signature, forged message" hazard is the theme of Part 3.

Debian OpenSSL (2008) is the case that proves the binding failure need not involve the authority at all. A well-meaning Debian patch removed code the maintainer thought was uninitialized-memory noise, and in doing so gutted the entropy of OpenSSL's random number generator. Keys generated on affected systems came from a space of only about 32,767 possibilities [3]. The X.509 structure was flawless; the private key underneath was one you could guess. With the entropy source reduced to essentially the process ID, affected keys had roughly 15 bits of randomness -- around 32,767 candidates for a given key type and size, enumerable in an afternoon. This is a randomness failure, catalogued under weak keys in Part 2, not a defect in certificate logic. The certificate did its job perfectly; the job was worthless.

Flame did not appear from nowhere. Its research ancestor is the 2008 rogue CA demonstration, in which Marc Stevens and six co-authors used a chosen-prefix MD5 collision -- on the order of 2^49 MD5 compression-function evaluations -- to obtain a working intermediate CA certificate from a RapidSSL branch that still signed with MD5 [25]. That was a controlled proof of concept. Flame was the same idea, refined, in the wild.

IncidentYearRoot causeQuestion it breaksThe lesson
DigiNotar2011Compromised trusted CA issued valid rogue certificatesBinding (whom)You cannot prevent a trusted CA from lying -- only detect it
Flame2012Novel MD5 chosen-prefix collision forged a code-signing certBinding (whom)A hash break subverts code signing; retire weak hashes in CA signing
Debian OpenSSL2008PRNG entropy gutted, leaving ~15-bit guessable keysBinding (weak key)A perfect certificate over a guessable key is worthless
2008 rogue CA (RapidSSL)2008Chosen-prefix MD5 collision, about 2^49 compressionsBinding (whom)MD5 in CA signing is fatal; the research ancestor of Flame

DigiNotar proved you cannot prevent a trusted authority from lying. That leaves two questions the field is still wrestling with: once a certificate is known to be bad, how do you take the trust back -- and if you cannot, how would you even find out? Take withdrawal first, because it is the one everyone assumes is solved and almost nobody has working.

8. Withdrawal: How Do I Stop Trusting Them, and Why That Is So Hard

Ask an engineer how certificate revocation works and you will get a clear description of a mechanism. Ask whether it works and the honest answer is: for most of the Web, for most of its history, it did not. Revocation is where the "how do I take the trust back?" question goes to fail, and it fails in a genealogy of increasingly clever attempts.

The original mechanism is the Certificate Revocation List, a periodically published, CA-signed list of revoked serial numbers, in X.509 since 1988 and profiled by RFC 5280 Section 5 [4]. The problem is size. A CRL grows with the number of revocations, routinely reaching megabytes, and downloading a multi-megabyte list to visit one site is untenable, so browsers cached them (reintroducing staleness) or stopped fetching them entirely [30].

The cost became concrete after Heartbleed triggered mass revocation in 2014. Serving its CA partner GlobalSign's suddenly-4.7 MB CRL, Cloudflare estimated, would have added about $400,000 a month in bandwidth -- roughly $953,000 at AWS pricing -- a load Cloudflare largely absorbed rather than a bill it paid [31]. Online revocation was still being reaffirmed as ineffective years afterward [32].

The fix seemed obvious: instead of downloading the whole list, ask about the one certificate you care about. The Online Certificate Status Protocol does exactly that -- a per-certificate query to a CA responder that returns a signed good, revoked, or unknown [33]. It has three fatal properties.

First, soft-fail: because the client cannot always reach the responder -- captive portals, responder downtime, or an attacker who simply blocks the request -- a failed check is ignored. That single design choice makes it useless against the attacker it targets, because a man-in-the-middle who can intercept your HTTPS can also block your OCSP query [34, 35].

"So soft-fail revocation checks are like a seat-belt that snaps when you crash. Even though it works 99% of the time, it's worthless because it only works when you don't need it." -- Adam Langley

Second, OCSP is a privacy leak: every check tells the certificate authority that a particular user, at a particular IP, is visiting a particular site, in real time -- reviving the online-directory hazard that certificates were invented to escape [34]. Third, it adds latency: a median around 300 milliseconds on every first connection [34], with more than 7% of checks timing out entirely [30], which is why Chrome disabled online revocation checking by default. Soft-fail is not a careless default; it is a forced one. If you make OCSP hard-fail instead -- block the connection whenever the check does not complete -- then any responder outage becomes an outage for every site that depends on it. So you either honor a blocked check (worthless against a MITM) or you refuse it (a self-inflicted denial of service). There is no third option at connection time.

Two fixes branched from OCSP. OCSP stapling moves the query off the client: the server fetches a fresh signed response and staples it into the TLS handshake, so the CA never sees the visitor and there is no per-connection round-trip [36]. But stapling is optional, so it inherits soft-fail -- an attacker just presents a certificate with no staple, and the client falls back to accepting it.

OCSP Must-Staple tried to close that gap with a flag in the certificate demanding a valid staple, turning a missing staple into a hard failure [37]. Hard-fail, though, means any hiccup in obtaining a staple takes the site down, so adoption stayed near zero and the feature became a footgun.

Ctrl + scroll to zoom
Five generations of revocation, each arrow labeled with the failure that forced the next. The line ends not by fixing revocation but by dissolving the need for it.

Then the whole branch was retired. Let's Encrypt stopped issuing Must-Staple certificates on 30 January 2025, dropped OCSP URLs from its certificates around 7 May 2025, and turned its OCSP responders off on 6 August 2025 [38] -- responders that at peak had served roughly 340 billion requests per month [39]. The CA/Browser Forum made OCSP optional [40]. The stated rationale was user privacy and reliability, not mere cleanup [41]. This is not a mechanism you tune; it is one the industry decommissioned.

MechanismClient costFreshnessPrivacyFail mode versus MITMStatus in 2026
CRLDownload the whole list (MBs)Publication intervalGood (offline)Stale or skippedFallback substrate
OCSPAbout 300 ms per checkReal-timeLeaks browsing to the CASoft-fail is worthlessOff (2025-08-06)
Stapling / Must-StapleZero client round-tripsStaple windowGoodMissing staple soft-fails, or hard-fail self-DoSLegacy, effectively dead
CRLiteO(1) local lookupPush interval (4x/day)Good (offline)Cannot be suppressedActive (Firefox)
Short-lived certsZero (no revocation data)Certificate expires in ~6 daysGoodNothing to checkActive (GA Jan 2026)

Every mechanism that tried to let you withdraw trust at connection time failed on soft-fail, privacy, latency, or brittleness. So the Web made a different move -- one that does not fix revocation at all. But before we get there, it had to answer DigiNotar's unanswered question: if you cannot prevent a rogue certificate, how would you even know one exists?

9. Detection: How Would I Know If They Lied? Certificate Transparency

The most important idea in modern PKI is an admission of defeat. You cannot stop a trusted authority from lying, DigiNotar proved that, so stop trying to prevent it and make lying impossible to hide instead.

Certificate Transparency (CT)

A system of public, append-only Merkle-tree logs that record every certificate a trusted authority issues. Browsers require proof that a certificate was logged before they will trust it, so mis-issuance leaves a permanent, public record that anyone can monitor.

Certificate Transparency, introduced by Ben Laurie, Adam Langley, and Emilia Kasper of Google in RFC 6962 in 2013, works like this: before a certificate can be trusted, it must be submitted to public logs, and each log returns a small signed receipt [42].

Signed Certificate Timestamp (SCT)

A log's signed promise to include a certificate in its append-only tree within a bounded time. Browsers require one or more SCTs, from independent logs, as a precondition for trusting a certificate.

A CT log is an append-only Merkle tree, and its power is that two things about it are cheaply provable. An inclusion proof (or audit proof) shows that a specific certificate is in the tree, using only about log2n\log_2 n hashes for a log of nn entries. A consistency proof shows that an earlier version of the tree is a prefix of a later one -- that the log only appended and never rewrote history -- also in O(logn)O(\log n) hashes [42]. Those logarithmic proofs are what make a log at Internet scale auditable by a small client [43].

Ctrl + scroll to zoom
Certificate Transparency in one exchange: the log issues an SCT, the browser demands one before trusting, and independent monitors read the log to catch mis-issuance.

The SCT reaches the browser by one of three paths: embedded in the certificate itself, delivered in a TLS handshake extension, or -- historically -- stapled into an OCSP response. The OCSP-stapled delivery path for SCTs is dying along with OCSP itself, which leaves the embedded and TLS-extension paths as the durable ones. The most common in practice is embedding, because it requires no server configuration. Whichever path carries it, the browser refuses to trust a publicly-trusted certificate that cannot prove it was logged. And because the logs are public, independent monitors read them continuously, so a domain owner can discover a mis-issued certificate for their own name, often within minutes, even though nothing stopped it from being issued [44].

Here is the mechanism under an SCT: recomputing a Merkle root from a leaf and a short audit path, the check a browser or auditor performs.

JavaScript Verify a Merkle inclusion proof in O(log n)
// Recompute a Merkle root from one leaf plus an audit path of sibling hashes.
// Toy hash shows the SHAPE; a real CT log uses SHA-256 over the same structure.
function h(x) { return "H(" + x + ")"; }

var leaf = h("cert:example.com");           // the certificate we want to prove
var auditPath = [                            // one sibling hash per tree level
{ side: "right", hash: "H(cert:sibling)" },
{ side: "right", hash: "H(subtree-2)" },
{ side: "left",  hash: "H(subtree-3)" }
];

function recomputeRoot(node, path) {
for (var i = 0; i < path.length; i++) {
  var s = path[i];
  node = (s.side === "left") ? h(s.hash + "|" + node) : h(node + "|" + s.hash);
}
return node;
}

var treeSize = 8; // eight certificates in this toy log
console.log("Log holds " + treeSize + " certificates.");
console.log("Proof length: " + auditPath.length + " hashes, about log2 of " + treeSize + ".");
console.log("Recomputed root: " + recomputeRoot(leaf, auditPath));
console.log("If it equals the log's signed root, inclusion is proven, in O(log n).");

Press Run to execute.

CT became mandatory for public trust when Chrome began requiring SCTs for certificates issued after 30 April 2018 [45], and Apple followed for Safari on 15 October 2018 [46]. Browsers accept SCTs only from logs admitted to their transparency programs [47]. The design goal was stated plainly in the RFC:

Publicly logging certificates "allows anyone to audit certificate authority activity and notice the issuance of suspect certificates as well as to audit the certificate logs themselves." -- RFC 6962

But read the verbs carefully. Audit. Notice. Not prevent.

CT closes the loop DigiNotar opened, but only as far as detection. A detected rogue certificate is still a valid, trusted certificate until it is revoked, and we have just seen that revocation is broken. That unresolved tension -- detected but still valid, and hard to take back -- is exactly what the 2024-2026 frontier attacks, and it does so with one surprisingly simple move.

10. State of the Art, 2024 to 2026

The whole modern frontier is one strategic move wearing five hats: shrink the trust window until withdrawal barely matters, corroborate issuance from many vantage points, keep every act of delegation public, and make the whole apparatus quantum-durable. Here are the layers, each sitting on the settled PKIX substrate.

Short-lived certificates are the dissolving move. Let's Encrypt's roughly six-day profile, which reached general availability in January 2026, issues certificates that carry no OCSP or CRL URLs at all -- a certificate that mis-issues simply expires before revocation would have mattered [48]. Revocation is not fixed; it is designed out. The price is a renewal cadence that only automation can sustain.

The 47-day validity schedule turns that from a boutique option into Web-wide policy. CA/Browser Forum Ballot SC-081v3, proposed by Apple (endorsed by Sectigo, Google, and Mozilla) and approved on 11 April 2025, steps the maximum TLS certificate validity down in stages: 398 days now, 200 days from 15 March 2026, 100 days from 15 March 2027, and 47 days from 15 March 2029, with domain-validation data reuse falling to just 10 days [49].

All four major browser vendors voted yes, and the schedule binds publicly trusted authorities through the CA/Browser Forum Baseline Requirements [40]. Its real function is a forcing function: certificates this short cannot be managed by hand, so the schedule mandates ACME-style automation across the entire Web [50].

CRLite handles the certificates that still live long enough to need revoking. It ingests every certificate from CT plus Internet scans, sorts them into revoked and valid, and encodes the answer as a cascade of Bloom filters, compressing roughly 300 MB of revocation data into about 1 MB that is refreshed four times a day and checked locally, offline, with zero false negatives [30, 51]. Lookups leak nothing and cannot be suppressed by a man-in-the-middle, which is the property OCSP never had [52]. After OCSP's retirement, plain CRLs are again the universal fallback beneath it.

Multi-Perspective Issuance Corroboration (MPIC) hardens the binding step at issuance time. Under CA/Browser Forum Ballot SC-067v3, a certificate authority must perform domain-control and CAA checks from several network vantage points, and the remote perspectives must corroborate the primary result or issuance is blocked -- which defeats localized BGP hijacks that could fool validation from a single location [53]. MPIC revives the "check from many vantage points" idea of the Perspectives and Convergence notary projects from around 2008 to 2011, which failed as user-facing products. The revival works because it runs inside the certificate authority at issuance time, not on the user's machine at connection time.

The requirement was adopted in 2024; enforcement began with two corroborating perspectives on 15 September 2025, ramping to three by 15 March 2026, four by 15 June 2026, and five by 15 December 2026, with perspectives required to sit at least 500 km apart [54].

Static, tile-based CT makes universal logging affordable. The Sunlight design, built by Let's Encrypt and Filippo Valsorda with the interoperable Static CT API, publishes the Merkle tree as immutable 256-element tiles served as plain static files from object storage, with no per-request database. The scale motivation is concrete: Let's Encrypt issues over four million certificates per day, and its Oak log passed 700 million entries, sizes that buckled the older relational design [55]. Tiling turns every proof read into a cache hit [56].

Merkle Tree Certificates and post-quantum certificates are the frontier. NIST's ML-DSA (FIPS 204) and SLH-DSA (FIPS 205) are the standardized post-quantum signatures a certificate will eventually use [57], and they hit a wall made of bytes.

SchemePost-quantumPublic key (bytes)Signature (bytes)Note
Ed25519no3264today's default, the bar to beat
RSA-2048no256256still common
ML-DSA-44yes1,3122,420the default post-quantum pick (FIPS 204)
FN-DSA-512yes897666smallest, but floating-point-dangerous to sign safely
SLH-DSA-128syes327,856most conservative security, worst size and speed (FIPS 205)

Post-quantum key agreement is already live -- around 1.8% of Cloudflare's TLS 1.3 connections in early 2024 -- but post-quantum certificates are not, and no certificate authority was expected to issue one before 2026 [58]. Put the layers side by side and the strategy is legible at a glance.

MethodWhat it doesWhat it buysStatus in 2026
Short-lived certificatesCertificates expire in daysMakes revocation barely matterGA January 2026 (Let's Encrypt)
47-day validity scheduleSteps max validity toward 47 days by 2029Forces automation Web-wideApproved April 2025 (CA/B Forum)
CRLitePushes all revocations, compressedFresh, private, offline withdrawalActive (Firefox)
MPICCorroborates issuance from many vantage pointsDefeats BGP-hijack mis-issuanceEnforcing since 2025-09-15
Tiled / Static CTServes the Merkle tree as static tilesCheap, scalable transparencyActive (Chrome accepts)
Merkle Tree CertificatesBatches certs under one PQ signatureDodges the post-quantum size wallDraft (IETF PLANTS WG)

The 2024-2026 frontier is a single move seen from five angles: shrink the trust window so withdrawal barely matters, corroborate issuance so mis-binding is harder, keep every delegation public so lies are visible, and make it all quantum-durable. Notice what is absent from that list -- a better cipher. The math was never the variable. Delegation always was.

This is the closest reachable approximation to a perfect trust layer. "Closest reachable" carries weight, because some of what stands between here and perfect is not an engineering backlog. It is a wall.

11. The Walls: Theoretical Limits and Open Problems

Some of this you cannot out-engineer. Underneath the 2024-2026 machinery are four structural limits, and no ballot or algorithm removes them.

The first is the deepest. You cannot prevent a rogue trusted authority; you can only detect one. In a system with hundreds of equally powerful roots, the trust of the whole equals the trust of its weakest member, and nothing in path validation flags a certificate that a trusted authority chose to sign. Certificate Transparency is the field's formal admission of this ceiling: it does not optimize prevention, because prevention is unavailable under an open many-root model. It optimizes detection latency [42].

That is the reader's final turn: after CT and CRLite and short-lived certs, it is tempting to conclude the problem is solved. It is not. The exploit window is shrunk, not closed, and the reason it can never reach zero is structural, not a missing feature.

The second is that the soft-fail/hard-fail fork of Section 8 is a structural wall, not an implementation gap. No connection-time status check escapes it: an attacker who can block the check defeats soft-fail, and hard-fail turns any responder outage into a self-inflicted denial of service for every dependent site. That is why the OCSP branch was retired rather than repaired [34].

The third is the revocation trilemma -- freshness, privacy, and scalability cannot be maximized together by any single online mechanism. This one is practically resolved by pre-distribution plus short lifetimes, but that is an escape from the trilemma, not a refutation of it; taken together, the historical record and the CRLite result suggest the trilemma is real and the field simply stopped paying its toll [30].

The fourth is that post-quantum signatures have no free lunch. No standardized post-quantum scheme matches Ed25519 on size and speed and conservative security at once; the three NIST standards each win a different corner, and the gap to an ideal is large enough that NIST opened a signatures onramp to search for better ones [58]. An "onramp" is NIST's term for a supplementary call for new candidate schemes after the main standardization round -- an admission that the standardized set does not yet contain a signature good enough for the certificate use case.

Around those walls sit the genuinely open problems. Preventing, rather than merely detecting, mis-issuance remains unsolved for the open Web; MPIC hardens one attack path, but the DigiNotar ceiling stands. Certificate Transparency has its own unfinished business: a misbehaving log can in principle show different trees to different clients -- a split view -- unless clients gossip their observations, and a complete, deployed gossip protocol that defeats split views without leaking privacy is not finished [43].

Fresh, private, complete, and cheap revocation at full Web scale has no consensus mechanism; CRLite is the best answer and still ships a bounded-staleness dataset [30]. The post-quantum size wall is unsolved for the general handshake, which is what Merkle Tree Certificates exist to dodge [59]. And name-constraint completeness over adversarial, worst-case-exponential path-building graphs is still an open corner of the validation problem [16].

Two of these deserve special mention because they are the new risks the SOTA created. The first is operational: short lifetimes convert "revocation is broken" into "your renewal automation must never fail," making the ACME pipeline a fresh single point of failure. No named large-scale post-mortem documents this yet; it is a structural consequence of the six-day and 47-day moves, flagged here rather than sourced to an incident [48].

The second is not technical at all, and it is the one the whole subject circles back to. I will state it as a judgment rather than a theorem: the hardest limit in PKI is who gets to be a trust anchor and who decides when to remove one. Root programs at Mozilla, Google, Apple, and Microsoft are the de-facto governors, and there is no technical mechanism that substitutes for that human judgment. The deepest limit is not mathematical. It is organizational, and consolidation makes it more fragile, not less.

Which means the practical question is never "is PKI secure?" but "am I using it in a way that respects what it can and cannot promise?" Here is how to do exactly that in 2026.

12. Using X.509 Correctly in 2026

Everything above collapses into one decision procedure and one misuse checklist you can run in a design review. Walk the tree in order.

Ctrl + scroll to zoom
A decision procedure for certificate handling in 2026. Each branch is one of the three questions -- binding, authorization, withdrawal, detection -- in operational clothes.

Now the rules behind the tree, with the parameters that matter.

  1. Never hand-roll validation. Most of this article's failure catalog is verifier bugs, and the classic study of non-browser software found certificate validation "completely broken" across a wide range of applications that rolled their own [60]. Use a maintained library, enable strict path validation, and do not skip Basic Constraints, Key Usage, EKU, or Name Constraints. Treat a critical extension you do not understand as fatal [4].

  2. Match the SAN, not the CN. Validate hostnames against subjectAltName. The legacy commonName-as-hostname path is deprecated and is the root of classic misuse -- null-prefix names and wildcard abuse [4].

  3. Make revocation a non-problem. Automate issuance with ACME and adopt short-lived (six-day) or 47-day-or-shorter certificates so a bad certificate expires on its own [48]. For the certificates that still live long, rely on CRLite and CRLs [30]. Do not deploy OCSP or Must-Staple as new work; the responders are off [39].

  4. If you run a private authority, constrain it. Issue a name-constrained root so it can only sign your namespace, enforce EKU, and keep it out of the public trust path [4]. This is the deliberate use of the enforcement that public code so often skips. ACME clients -- Certbot, lego, acme.sh, and Caddy's automatic HTTPS -- are the renewal substrate the 47-day schedule quietly assumes. Choosing and monitoring one is now part of certificate design, not an afterthought.

  5. Authorize issuance with CAA. Publish DNS Certification Authority Authorization records naming which authorities may issue for your domain [61]. Under MPIC, those records are now checked from multiple network perspectives, so they are harder to spoof [53].

  6. Detect mis-issuance for your own names. Run or subscribe to a Certificate Transparency monitor, reading the logs through the Static CT tiles [56]. This is how you personally exercise the detection that CT makes possible [45].

  7. Plan for post-quantum without over-rotating. Deploy post-quantum key agreement (an ML-KEM hybrid) now, but wait on post-quantum certificates and track the Merkle Tree Certificate and ML-DSA rollout instead [58]. There is no reason to ship kilobyte-scale certificate signatures before the format that tames them lands [59].

  8. Do not pin keys. Prefer CT monitoring plus CAA over HPKP-style public-key pinning, which browsers deprecated in 2018 after it proved to be a self-inflicted denial-of-service and ransom risk [62].

Each misuse below maps one-to-one to a named break earlier in this article and to its fix. If you recognize your own system in the left column, you already know which section to reread.

Common misuseMaps to which named breakThe fix
Skipping Basic Constraints, accepting a leaf as a CAMS02-050, CVE-2021-3450Enable strict path validation
Matching the CN instead of the SANnull-prefix and wildcard abuseMatch subjectAltName only
Deploying OCSP or Must-Staple as new worksoft-fail, Must-Staple self-DoSShort-lived certs plus CRLite and CRLs
Treating a public CA-signed cert as inherently "safe"DigiNotarMonitor CT; question the delegation
Long-lived certificates and manual renewalHeartbleed mass-revocation costAutomate with ACME, 47 days or shorter
Explicit ECC parameters, hand-rolled cryptoCurveBall (CVE-2020-0601)Maintained libraries, standard curves
Pinning keys with HPKPHPKP self-DoS and ransom pinningCT monitoring plus CAA

Notice that every rule is the same rule wearing different clothes: know whom you are trusting, to say what, and how you would know if they lied. The folklore that gets this wrong is dense, and it causes real incidents. Here are the misconceptions worth dismantling.

13. Seven Half-Truths That Cause Real Incidents

Frequently asked questions

Does certificate revocation actually work?

Historically, mostly not. Online checks soft-fail, which makes them worthless against the man-in-the-middle they target, and they leak your browsing to the certificate authority while adding latency [34]. The 2026 answer is not better revocation but short-lived certificates that dissolve the need [48] plus CRLite and CRLs that push the remaining data offline [30]. Do not build new systems on OCSP -- its responders are off [39].

Does the padlock mean the site is safe or legitimate?

No. The padlock means the connection is encrypted and authenticated to a name that passed domain-control validation. It does not mean the operator is honest, the content safe, or the business real -- DigiNotar's forged Google certificate produced a perfectly closed padlock [1]. Whom you are trusting, and to say what, is a separate question the padlock cannot answer.

Is a self-signed certificate insecure and a CA-signed one secure?

No. A CA-signed certificate is only as trustworthy as the authority that signed it and the validation that checked it, and DigiNotar's rogue certificates were fully CA-signed [24]. For internal use, a name-constrained private root can be safer than a public one, because it physically cannot issue outside your namespace [4]. "Signed by a CA" is not a synonym for "safe."

Is the Common Name the hostname the browser checks?

No. Modern validation matches the subjectAltName extension, not the Common Name, and CN-as-hostname is deprecated precisely because it was the root of null-prefix and wildcard abuse [4]. If your tooling still relies on the CN field for hostname matching, it is running a validation path the standards left behind.

Is OCSP Must-Staple a best practice?

No -- it is a legacy footgun on top of a retired substrate. Must-Staple hard-fails, so any hiccup in obtaining a staple takes your site down [37], and it sits on OCSP responders that Let's Encrypt turned off in August 2025 [39]. Present it historically. Design revocation around short lifetimes and CRLite instead.

Does Certificate Transparency prevent mis-issuance?

No -- it detects it. CT makes every issued certificate leave a public, permanent record so a rogue certificate can be noticed, but it does not stop the certificate from being issued or trusted [42]. Detection, not prevention, is the achievable ceiling for an open, many-root system. A logged rogue certificate is valid until a human gets it distrusted.

Are EV certificates or longer chains meaningfully more secure?

Not in the way people assume. This is my read of the evidence rather than a theorem, but Extended Validation buys little practical protection once its distinct browser indicator is gone, and extra intermediate certificates add attack surface rather than safety. Chain length is not chain trustworthiness -- what matters is whom the chain delegates to, not how many hops it takes.

Every one of these dissolves into the same sentence -- which is the conclusion's job to deliver, back where the article began.

The Trust Was the Bug

Go back to that DigiNotar certificate one last time. It was cryptographically perfect. It was trusted by every browser on Earth. And it was a total compromise -- because the question that mattered was never "does this verify?" [1]

Look at the whole catalog with that in mind. DigiNotar, Flame, the 2008 rogue CA, Debian's guessable keys, MS02-050, CurveBall, OpenSSL's strict-mode regression, Spooky SSL -- in every single case, the RSA, ECDSA, and SHA math did exactly what it promised [2]. The signatures verified. The hashes hashed. The variable was always delegation: whom a trusted party vouched for [3], what it was allowed to say [17], and whether anyone could take the trust back. Not once was the primitive the weak link.

And read the 2024-2026 answer the same way, because it is one move, not five. The Web could not make certificate authorities honest, so it made them public with Certificate Transparency [42], corroborated with multi-perspective issuance [53], and short-lived with the 47-day schedule [49] -- shrinking the trust window until a lie expires before it can spread. The engineering did not find a better cipher. It changed what it demanded of delegation.

That is the same payoff the rest of this series keeps arriving at from different directions. The RSA math was always fine, as Part 1 argued about adversary models. The primitive was never the variable, as Part 3 showed about serialization. Here it is again, in the machinery of trust itself: the cryptography was innocent, and the delegation was guilty.

So take the one tool this article was built to give you. When the next certificate incident crosses your feed -- and there will be a next one -- do not reach for the algorithm. Reach for the sentence: whom am I trusting, to say what, and how would I know if they lied? It will sort the break into binding, authorization, withdrawal, or detection before you have finished reading the headline.

That lens outlives every algorithm transition and every CA/Browser Forum ballot. RSA will yield to ML-DSA; OCSP already yielded to CRLite; 398-day certificates are yielding to 47-day ones. The three questions do not change. Which is exactly why this is Part 4 of a field guide to protocol design, and not a chapter on parsing certificates.

Study guide

Key terms

X.509 certificate
A signed data structure that binds a public key to a name and usage constraints, verifiable offline by anyone holding the issuer's key.
ASN.1 and DER
The description language and canonical binary encoding X.509 uses, so a signature covers one unambiguous sequence of bytes.
Trust anchor and root store
A certificate authority key trusted a priori, and the curated set of such keys a browser or OS root program ships.
Path building (RFC 4158)
The graph search that discovers a candidate chain from a leaf certificate up to some trust anchor; worst-case exponential.
Path validation (RFC 5280 Section 6)
The linear state machine that checks one chosen chain: signatures, validity dates, and the authorization extensions.
Basic Constraints
The extension stating whether a key may act as a CA and how many sub-CAs may appear below it.
Extended Key Usage (EKU)
The machine-readable list of purposes a key may serve, such as TLS server authentication or code signing.
Name Constraints
The name subtrees a sub-CA may issue within, intersected down the certification path.
Certificate Transparency (CT)
Public, append-only Merkle-tree logs of every issued certificate; browsers require proof of logging before trusting.
Signed Certificate Timestamp (SCT)
A log's signed promise to include a certificate, required by browsers as a precondition for trust.

References

  1. Fox-IT (2012). Black Tulip: Report of the investigation into the DigiNotar Certificate Authority breach. https://github.com/juliocesarfort/public-pentesting-reports/blob/master/Fox-IT/Fox-IT_-_DigiNotar.pdf
  2. Marc Stevens (2013). Counter-cryptanalysis. https://eprint.iacr.org/2013/358
  3. NVD (2008). CVE-2008-0166: OpenSSL predictable random number generator (Debian). https://nvd.nist.gov/vuln/detail/CVE-2008-0166
  4. David Cooper, Stefan Santesson, Stephen Farrell, Sharon Boeyen, Russ Housley, & Tim Polk (2008). RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile. https://datatracker.ietf.org/doc/html/rfc5280
  5. ITU-T Recommendation X.690: ASN.1 encoding rules (BER, CER, DER). https://www.itu.int/rec/T-REC-X.690
  6. Whitfield Diffie & Martin Hellman (1976). New Directions in Cryptography. https://ieeexplore.ieee.org/document/1055638
  7. Loren M. Kohnfelder (1978). Towards a Practical Public-Key Cryptosystem. https://dspace.mit.edu/handle/1721.1/15993
  8. ITU-T Recommendation X.509: The Directory -- Public-key and attribute certificate frameworks. https://www.itu.int/rec/T-REC-X.509
  9. Steve Kent (1993). RFC 1422: Privacy Enhancement for Internet Electronic Mail, Part II. https://datatracker.ietf.org/doc/html/rfc1422
  10. Alan Freier, Philip Karlton, & Paul Kocher (2011). RFC 6101: The Secure Sockets Layer (SSL) Protocol Version 3.0. https://datatracker.ietf.org/doc/html/rfc6101
  11. Russ Housley, Warwick Ford, Tim Polk, & David Solo (1999). RFC 2459: Internet X.509 Public Key Infrastructure Certificate and CRL Profile. https://datatracker.ietf.org/doc/html/rfc2459
  12. Alma Whitten & J. D. Tygar (1999). Why Johnny Can't Encrypt: A Usability Evaluation of PGP 5.0. https://www.usenix.org/conference/8th-usenix-security-symposium/why-johnny-cant-encrypt-usability-evaluation-pgp-50
  13. Wikipedia Web of trust. https://en.wikipedia.org/wiki/Web_of_trust
  14. Carl Ellison, Bill Frantz, Butler Lampson, Ron Rivest, Brian Thomas, & Tatu Ylonen (1999). RFC 2693: SPKI Certificate Theory. https://datatracker.ietf.org/doc/html/rfc2693
  15. Paul Hoffman & Jakob Schlyter (2012). RFC 6698: The DNS-Based Authentication of Named Entities (DANE) TLSA. https://datatracker.ietf.org/doc/html/rfc6698
  16. Matt Cooper, Yuriy Dzambasow, Peter Hesse, Susan Joseph, & Richard Nicholas (2005). RFC 4158: Internet X.509 Public Key Infrastructure -- Certification Path Building. https://datatracker.ietf.org/doc/html/rfc4158
  17. NVD (2002). CVE-2002-0862: Microsoft CryptoAPI basic constraints validation flaw. https://nvd.nist.gov/vuln/detail/CVE-2002-0862
  18. Moxie Marlinspike (2011). sslsniff: an SSL/TLS MITM tool that exploits implementations not verifying BasicConstraints. https://github.com/moxie0/sslsniff
  19. OpenSSL Project (2021). OpenSSL Security Advisory (CVE-2021-3450): CA certificate check bypass with X509_V_FLAG_X509_STRICT. https://openssl-library.org/news/secadv/20210325.txt
  20. NVD (2014). CVE-2014-1266: Apple TLS goto fail signature-verification bypass. https://nvd.nist.gov/vuln/detail/CVE-2014-1266
  21. NVD (2020). CVE-2020-0601: Windows CryptoAPI ECC certificate spoofing (CurveBall). https://nvd.nist.gov/vuln/detail/CVE-2020-0601
  22. NVD (2022). CVE-2022-3602: OpenSSL X.509 punycode name-constraint buffer overflow (Spooky SSL). https://nvd.nist.gov/vuln/detail/CVE-2022-3602
  23. OpenSSL Project (2022). OpenSSL Security Advisory (CVE-2022-3602 / CVE-2022-3786): X.509 punycode buffer overflows. https://openssl-library.org/news/secadv/20221101.txt
  24. Wikipedia DigiNotar. https://en.wikipedia.org/wiki/DigiNotar
  25. Marc Stevens, Alexander Sotirov, Jacob Appelbaum, Arjen Lenstra, David Molnar, Dag Arne Osvik, & Benne de Weger (2009). Short Chosen-Prefix Collisions for MD5 and the Creation of a Rogue CA Certificate. https://eprint.iacr.org/2009/111
  26. Comodo (2011). Comodo Fraud Incident: report on the March 2011 registration-authority breach. https://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
  27. Google (2013). Enhancing digital certificate security (TURKTRUST intermediate misissuance). https://security.googleblog.com/2013/01/enhancing-digital-certificate-security.html
  28. Google (2017). Chrome's Plan to Distrust Symantec Certificates. https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html
  29. Mozilla (2016). Distrusting New WoSign and StartCom Certificates. https://blog.mozilla.org/security/2016/10/24/distrusting-new-wosign-and-startcom-certificates/
  30. Mozilla Security Engineering (2020). CRLite: Speeding Up Secure Browsing (Part 1). https://blog.mozilla.org/security/2020/01/09/crlite-part-1-all-web-pki-revocations-compressed/
  31. Cloudflare (2014). The Hard Costs of Heartbleed. https://blog.cloudflare.com/the-hard-costs-of-heartbleed/
  32. Adam Langley (2014). Revocation still doesnt work. https://www.imperialviolet.org/2014/04/29/revocationagain.html
  33. Stefan Santesson, Michael Myers, Rich Ankney, Ambarish Malpani, Slava Galperin, & Carlisle Adams (2013). RFC 6960: X.509 Internet PKI Online Certificate Status Protocol (OCSP). https://datatracker.ietf.org/doc/html/rfc6960
  34. Adam Langley (2012). Revocation checking and Chrome's CRL. https://www.imperialviolet.org/2012/02/05/crlsets.html
  35. Adam Langley (2011). Revocation doesnt work. https://www.imperialviolet.org/2011/03/18/revocation.html
  36. Donald Eastlake (2011). RFC 6066: Transport Layer Security (TLS) Extensions. https://datatracker.ietf.org/doc/html/rfc6066
  37. Phillip Hallam-Baker (2015). RFC 7633: X.509v3 Transport Layer Security (TLS) Feature Extension. https://datatracker.ietf.org/doc/html/rfc7633
  38. Let's Encrypt (2024). Ending OCSP Support in 2025. https://letsencrypt.org/2024/12/05/ending-ocsp
  39. Let's Encrypt (2025). OCSP Service Has Reached End of Life. https://letsencrypt.org/2025/08/06/ocsp-service-has-reached-end-of-life
  40. CA/Browser Forum Baseline Requirements for the Issuance and Management of Publicly-Trusted TLS Certificates. https://cabforum.org/working-groups/server/baseline-requirements/documents/
  41. ISRG Ending OCSP. https://www.abetterinternet.org/post/ending-ocsp/
  42. Ben Laurie, Adam Langley, & Emilia Kasper (2013). RFC 6962: Certificate Transparency. https://datatracker.ietf.org/doc/html/rfc6962
  43. Ben Laurie, Eran Messeri, & Rob Stradling (2021). RFC 9162: Certificate Transparency Version 2.0. https://datatracker.ietf.org/doc/html/rfc9162
  44. Wikipedia Certificate Transparency. https://en.wikipedia.org/wiki/Certificate_Transparency
  45. Google Chrome Certificate Transparency in Chrome. https://googlechrome.github.io/CertificateTransparency/
  46. Apple Apple's Certificate Transparency policy. https://support.apple.com/en-us/103214
  47. Google Certificate Transparency Log Policy. https://certificate.transparency.dev/google/
  48. Let's Encrypt (2025). Six-Day and IP Address Certificates. https://letsencrypt.org/2025/01/16/6-day-and-ip-certs
  49. CA/Browser Forum (2025). Ballot SC-081v3: Introduce Schedule of Reducing Validity and Data Reuse Periods. https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/
  50. DigiCert (2025). TLS Certificate Lifetimes Will Officially Reduce to 47 Days. https://www.digicert.com/blog/tls-certificate-lifetimes-will-officially-reduce-to-47-days
  51. James Larisch, David Choffnes, Dave Levin, Bruce Maggs, Alan Mislove, & Christo Wilson (2017). CRLite: A Scalable System for Pushing All TLS Revocations to All Browsers (PDF). https://obj.umiacs.umd.edu/papers_for_stories/crlite_oakland17.pdf
  52. James Larisch, David Choffnes, Dave Levin, Bruce Maggs, Alan Mislove, & Christo Wilson (2017). CRLite: A Scalable System for Pushing All TLS Revocations to All Browsers. https://ieeexplore.ieee.org/document/7958580
  53. CA/Browser Forum (2024). Ballot SC-067v3: Require Multi-Perspective Issuance Corroboration. https://cabforum.org/2024/08/05/ballot-sc067v3-require-domain-validation-and-caa-checks-to-be-performed-from-multiple-network-perspectives-corroboration/
  54. Sectigo Multi-Perspective Issuance Corroboration (MPIC) FAQ. https://www.sectigo.com/mpic-faq
  55. Let's Encrypt (2024). Introducing Sunlight, a new Certificate Transparency log design. https://letsencrypt.org/2024/03/14/introducing-sunlight
  56. C2SP Static CT API (tile-based Certificate Transparency logs). https://c2sp.org/static-ct-api
  57. NIST (2024). FIPS 204: Module-Lattice-Based Digital Signature Standard (ML-DSA). https://csrc.nist.gov/pubs/fips/204/final
  58. Cloudflare (2024). The state of the post-quantum Internet. https://blog.cloudflare.com/pq-2024/
  59. David Benjamin, Devon OBrien, Bas Westerbaan, Luke Valenta, & Filippo Valsorda (2025). Merkle Tree Certificates (draft-davidben-tls-merkle-tree-certs). https://datatracker.ietf.org/doc/draft-davidben-tls-merkle-tree-certs/
  60. Martin Georgiev, Subodh Iyengar, Suman Jana, Rishita Anubhai, Dan Boneh, & Vitaly Shmatikov (2012). The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software. https://dl.acm.org/doi/10.1145/2382196.2382204
  61. Phillip Hallam-Baker, Rob Stradling, & Jacob Hoffman-Andrews (2019). RFC 8659: DNS Certification Authority Authorization (CAA) Resource Record. https://datatracker.ietf.org/doc/html/rfc8659
  62. Chris Evans, Chris Palmer, & Ryan Sleevi (2015). RFC 7469: Public Key Pinning Extension for HTTP. https://datatracker.ietf.org/doc/html/rfc7469