← All posts Digital Trust · Part 1 of 7

Anatomy of a Modern PKI

Every non-trivial system eventually arrives at the same uncomfortable question: how do you know the thing on the other end of the connection is what it claims to be? The real question isn't "is the data encrypted" (that is the easy part) but "whose key is this, and why should I believe that?" Public Key Infrastructure is the answer the industry has settled on, and it is worth understanding properly, because a large share of production incidents attributed to "a certificate problem" are really a misunderstanding of what PKI actually is.

This is the first article in a series on architecting digital trust. Before we get to lifecycle, automation, agility and scale, we need a shared mental model of the machine itself. So this piece is the anatomy lesson: what PKI delivers, how an X.509 certificate is built, how chains of trust are assembled and validated, and where the whole thing tends to bite.

I'll say this up front: PKI is not a product you buy, and it is not a box of cryptography. It is an operational system for distributing and revoking trust. The maths is the least interesting part.

What PKI actually delivers

Strip away the acronyms and PKI is a mechanism for binding a public key to an identity in a way that a third party will believe. From that single binding, four architectural properties fall out:

  • Authentication. A relying party can verify that a peer controls the private key corresponding to a certified public key, and that the key is bound to a named identity.
  • Integrity. Signatures over content (or over a TLS handshake transcript) let a verifier detect any tampering after the fact.
  • Confidentiality, or more precisely key establishment. Certificates rarely encrypt bulk data; they authenticate the parties so an ephemeral session key can be agreed safely. This distinction matters more than people think.
  • Non-repudiation. A signature made with a key that only one party controls can be attributed to that party later. This is the weakest of the four in practice, because it depends entirely on key custody being defensible.

Notice that three of those four are not really cryptographic claims at all. They are claims about who holds a key. The cryptography is largely a solved problem. The hard problem, the thing PKI exists to manage, is trust: a transferable, revocable, time-bounded assertion that this key belongs to that identity.

PKI is not cryptography with extra steps. It is a system for distributing trust at scale, and the certificates are merely that trust made portable.

The anatomy of an X.509 certificate

A certificate is a signed assertion, encoded in ASN.1 and serialised with DER (the Distinguished Encoding Rules), structured according to X.509 and profiled for the internet by RFC 5280. At the top level it has three parts: the tbsCertificate (the "to-be-signed" body holding all the actual fields), the signatureAlgorithm identifier, and the signatureValue, which is the CA's signature over the DER encoding of the tbsCertificate. Get this structure into your head, because path validation is fundamentally "re-hash the tbsCertificate and check the issuer's signature over it", repeated up the chain.

The fields that carry identity

Within the tbsCertificate, a handful of fields do the heavy lifting: the serial number (unique per issuer, and a real revocation handle, not decoration), the issuer and subject distinguished names, the validity window (notBefore/notAfter), and the subjectPublicKeyInfo that carries the certified public key and its algorithm. In the modern WebPKI the subject DN is largely vestigial. Identity now lives in the extensions.

The extensions that actually matter

Extensions are where real-world certificates live or die. These are the ones I check first whenever something is misbehaving:

  • Basic Constraints: is this a CA certificate (cA:TRUE) or a leaf? And if a CA, what pathLenConstraint applies? A leaf certificate presented as if it were a CA, or an intermediate with the wrong pathlen, breaks validation hard.
  • Key Usage: the cryptographic operations the key is permitted: digitalSignature, keyEncipherment, keyCertSign, cRLSign. A CA without keyCertSign cannot legitimately sign certificates.
  • Extended Key Usage: the higher-level purpose: serverAuth, clientAuth, codeSigning, and so on. EKU is increasingly enforced and increasingly chained, so a constraint here on an intermediate now limits its leaves.
  • Subject Alternative Name (SAN): where hostnames and identities actually live for TLS. Common Name matching is dead; if it is not in the SAN, modern clients do not see it.
  • Authority Key Identifier (AKI) and Subject Key Identifier (SKI): the breadcrumbs a path builder uses to connect a child's AKI to its issuer's SKI. Wrong or missing values here cause most "I have the right certs but it still won't chain" puzzles.
  • Authority Information Access (AIA): points to the issuer's certificate (caIssuers) and to OCSP. The caIssuers URL is how a verifier fetches a missing intermediate; ignore it and you are relying on the server to send a complete chain.
  • CRL Distribution Points: where to fetch the revocation list. Easy to configure, easy to forget, and a silent single point of failure when the endpoint goes dark.

Here is an annotated leaf, trimmed to the parts that matter:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4a:7f:2c:9e:11:b0:55:e3:...        # revocation handle, unique per issuer
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=GB, O=Example Issuing CA, CN=Example TLS Issuing CA G2
        Validity
            Not Before: Nov 15 00:00:00 2025 GMT
            Not After : Feb 13 23:59:59 2026 GMT   # ~90 days; short-lived by design
        Subject: CN=www.example-service.test
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                ASN1 OID: prime256v1, NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE                          # this is a leaf, not a CA
            X509v3 Key Usage: critical
                Digital Signature                 # no keyCertSign here
            X509v3 Extended Key Usage:
                TLS Web Server Authentication      # serverAuth only
            X509v3 Subject Alternative Name:
                DNS:www.example-service.test, DNS:example-service.test
            X509v3 Subject Key Identifier:
                3B:9A:...:F1                       # this cert's key fingerprint
            X509v3 Authority Key Identifier:
                keyid:0C:7E:...:A4                 # must match issuer's SKI
            Authority Information Access:
                CA Issuers - URI:http://aia.example-issuing.test/ca-g2.cer
                OCSP - URI:http://ocsp.example-issuing.test
            X509v3 CRL Distribution Points:
                Full Name: URI:http://crl.example-issuing.test/g2.crl
    Signature Algorithm: ecdsa-with-SHA256
        30:45:02:21:00:...                         # CA signature over tbsCertificate

The chain of trust

No single certificate is trustworthy on its own. Trust is anchored at a root CA, a self-signed certificate that a relying party has decided, out of band, to believe. Below it sit one or more intermediate (issuing) CAs, and at the bottom are the leaf (end-entity) certificates issued to servers, clients and devices. Each link is the issuer signing the subject below it.

          +-----------------------------+
          |   Root CA  (self-signed)    |   offline, in an HSM
          |   CA:TRUE, pathlen:1        |   trust anchor in the store
          +--------------+--------------+
                         | signs
                         v
          +-----------------------------+
          | Intermediate / Issuing CA   |   online, day-to-day issuance
          | CA:TRUE, pathlen:0          |   EKU + name constraints applied
          +--------------+--------------+
                         | signs
            +------------+------------+
            v                         v
   +-----------------+       +-----------------+
   |   Leaf  (TLS)   |       |  Leaf (client)  |   CA:FALSE
   |  serverAuth     |       |  clientAuth     |   short-lived
   +-----------------+       +-----------------+

Why intermediates exist

The most important architectural decision in any hierarchy is that the root almost never signs leaves directly. Intermediates exist for concrete reasons:

  • Root protection. The root's private key is the keystone of the entire trust domain. Keep it offline, in an HSM, powered on only for ceremony. If it never touches a network, it cannot be compromised over one.
  • Delegation and blast radius. Separate intermediates for TLS, client auth, code signing or per-business-unit issuance mean a compromise or mis-issuance is contained to one intermediate, which can be revoked without re-rooting the planet.
  • Cross-signing. An intermediate can be signed by more than one root, letting a new hierarchy borrow the ubiquity of an established trust anchor while its own root propagates into trust stores.
  • Agility. Rotating an intermediate is an operational event. Rotating a root is a multi-year migration. The layer of indirection is what buys room to move, a theme the crypto-agility article returns to.

Path building versus path validation

This is the distinction most often missing from engineers' mental models, and it is the source of an outsized share of production incidents.

Path building is the search problem: given a leaf and a set of candidate certificates, find a chain from the leaf up to a trusted anchor. It uses AKI/SKI hints and issuer/subject name matching to link certificates, and it can fail even when a valid chain exists, simply because the right intermediate was never supplied. Path validation (RFC 5280, section 6) is the verification problem: given a candidate chain, check that every signature verifies, every certificate is in its validity window, basic constraints and pathlen hold, key usage and EKU are consistent, name constraints are honoured, and nothing is revoked.

They fail differently, and conflating them wastes hours. "It chains fine on the laptop but not in production" is almost always a path-building failure: the laptop happened to have the intermediate cached, the production host did not, and the server was not configured to send it.

The classic production failures

  • Missing intermediate. The server sends only its leaf. Clients with the intermediate cached succeed; clean clients fail. Intermittent, environment-dependent, maddening.
  • Wrong chain order. Some stacks are strict about leaf-first ordering in the presented chain. A reordered or root-included bundle can trip them.
  • Expired intermediate. The leaf is valid, but a CA certificate above it has lapsed. The whole chain is dead and the leaf's own dates look fine, which sends people looking in the wrong place.
  • Name-constraint surprises. An intermediate constrained (via nameConstraints) to .internal.example will refuse to validate a leaf for a public name. That is correct behaviour, but it looks like a bug to whoever filed the ticket.

A two-line check settles most of these before the speculation starts:

# What is the server actually sending? (note the chain it presents)
openssl s_client -connect host.example.test:443 -servername host.example.test -showcerts </dev/null

# Validate a leaf against an explicit chain, offline and deterministic
openssl verify -CAfile root.pem -untrusted intermediate.pem leaf.pem

# Inspect a single certificate's extensions
openssl x509 -in leaf.pem -noout -text

# Confirm the link: child AKI must equal issuer SKI
openssl x509 -in leaf.pem -noout -ext authorityKeyIdentifier
openssl x509 -in intermediate.pem -noout -ext subjectKeyIdentifier

Trust stores and relying parties

A chain is only as meaningful as the anchor it terminates at, and anchors live in trust stores. A trust store is a curated set of root certificates that a relying party has decided to believe: the OS trust store, a browser's bundled roots, a language runtime's CA file, or a bespoke store you ship with an application. Path validation succeeds only if the chain ends at a root in the verifier's store. This is the part operators forget: the same certificate is valid or invalid depending entirely on who is asking.

Public WebPKI versus private PKI

Two very different worlds share the same X.509 machinery:

  • Public WebPKI. Roots are distributed in OS and browser trust stores worldwide and governed by the CA/Browser Forum's Baseline Requirements. You get ubiquity for free (any browser will trust your leaf), but you accept external rules: capped validity, mandatory logging, audited issuance, and policy changes you do not control. You are a tenant on someone else's trust fabric.
  • Private / internal PKI. You operate your own root and distribute it to your own fleet. You set the policy, the validity periods, the profiles and the name space. The cost is that you own distribution: a leaf from your internal CA is worthless on any device that has not been told to trust your root. Most enterprise pain lives precisely at that distribution boundary.

Choosing between them is an architectural decision, not a procurement one. Internet-facing services almost always need public trust; internal service meshes, device fleets and machine identity are usually better served by a private hierarchy you fully control. The later articles on machine identity and enterprise scale pick up from there.

Things that bite you

The same failures recur across organisations. In rough order of how often they show up:

  • The "valid leaf, dead chain" trap. Monitoring watches leaf expiry and ignores the intermediates and the root. An intermediate lapses and every leaf beneath it dies simultaneously. Monitor the whole chain, including the CA certificates.
  • Treating the server bundle as optional. Always configure servers to present leaf plus intermediate(s). Do not rely on clients fetching via AIA. Many will not, and the ones that do add latency and a network dependency to your handshake.
  • Confusing "encrypted" with "authenticated". A connection can be perfectly encrypted to an attacker. Confidentiality without authentication is theatre; the certificate's job is the authentication half.
  • Long-lived everything. Ten-year leaves feel convenient until you need to rotate an algorithm or revoke at scale. Once issuance is automated, short validity stops being a burden, and that is the premise of the ACME article later in this series.
  • Forgetting the relying party. "It works for me" means your store has the anchor. Always reason from the verifier's trust store, not your own.
  • Critical extensions you do not understand. A critical extension a verifier cannot process must cause rejection per RFC 5280. Mark extensions critical deliberately, not reflexively.

None of these are exotic. They are the boring, recurring failures of an operational system that people insist on treating as a cryptographic one.

Where this leaves us

The reframing I would most like you to take away: a PKI is not the certificates, and it is certainly not the algorithms. It is the living system that issues, distributes, validates and, just as importantly, revokes trust across a population of relying parties who will never meet each other. The X.509 structure, the chain, the trust store and the path-validation rules are the grammar in which that trust is expressed. Get the grammar right and the rest of the system has a foundation to stand on; get it wrong and no amount of clever cryptography will save it. The next article follows a single certificate through its entire lifecycle, from key generation and a PKCS#10 request, through issuance and deployment, to renewal and revocation. That lifecycle is where these anatomical parts either work together or quietly fall apart.

Next: The Certificate Lifecycle →