Public Key Infrastructure (PKI) is the system of roles, policies, hardware, software, and procedures needed to create, manage, distribute, use, store, and revoke digital certificates. It's the trust plumbing that makes HTTPS, email signing, VPN authentication, and code signing work at scale.
The core problem PKI solves: when you connect to bank.com, how do you know you're actually talking to the bank and not an attacker? PKI provides a chain of trust — your browser trusts a small set of root Certificate Authorities (CAs), which in turn vouch for other CAs, which in turn vouch for the website's certificate. If the chain is valid, you can trust who you're talking to.
Root CAs are the anchors of trust. Their public keys are hardcoded into operating systems and browsers — there are roughly 150 trusted root CAs in a modern browser. Because compromising a root CA would be catastrophic, root CA private keys are stored offline in hardware security modules (HSMs), often in air-gapped facilities with physical security controls. Root CAs almost never issue certificates directly.
Intermediate CAs sit between root CAs and end-entity certs. They're online and do the day-to-day work of issuing certificates. Using intermediates means the root key stays offline — if an intermediate is compromised, it can be revoked without touching the root. Most CAs operate multiple intermediates for different use cases (TLS, code signing, email).
Leaf certificates (also called end-entity or server certificates) are what websites, APIs, and services present. They can only be used — not used to sign other certificates. The Basic Constraints extension enforces this with CA:FALSE.
X.509 is the standard format for public key certificates used in TLS, S/MIME, and most other PKI applications. Here's what's inside:
The server admin generates a public/private key pair. The private key never leaves the server — it's used to prove ownership. Common choices: RSA-2048 or RSA-4096 (older, widely compatible), ECDSA P-256 (smaller, faster, recommended for new setups).
The admin creates a CSR containing the public key, the domain name(s), and organisation details. The CSR is signed with the private key to prove the requester holds it. The CSR is sent to the CA — it contains no secrets. Command: openssl req -new -key server.key -out server.csr
The CA must confirm the requester actually controls the domain. For DV (Domain Validated) certs — the cheapest and most common type — this is automated: the CA checks a DNS TXT record, a specific file on the web server, or an email to the domain's admin contact. OV (Organisation Validated) adds verification of the legal entity. EV (Extended Validation) requires a thorough identity check and used to show a green address bar in browsers (now phased out visually but still more rigorous).
The CA takes the CSR contents, adds its own metadata (issuer, validity dates, serial number, extensions), and signs the whole thing with its private key using a hashing algorithm (typically SHA-256). This signature is the proof — anyone with the CA's public key can verify it. The signed certificate is sent back to the server admin.
During a TLS handshake, the server sends its leaf certificate plus any intermediate certificates. The browser walks the chain: verifies the leaf cert was signed by the intermediate, verifies the intermediate was signed by the root, and checks that the root is in its trusted store. If all signatures are valid and no cert is expired or revoked, the connection proceeds.
If a private key is compromised or a cert is issued incorrectly, the certificate needs to be revoked before it expires. Two mechanisms handle this:
| Method | How it works | Verdict |
|---|---|---|
| CRL Certificate Revocation List |
The CA publishes a signed list of revoked serial numbers at a URL embedded in each cert. Clients download and check the list. CRLs can be large and are only updated periodically — a revoked cert may still appear valid between CRL updates. | Legacy |
| OCSP Online Certificate Status Protocol |
Client sends the cert's serial number to the CA's OCSP responder and gets a real-time "good", "revoked", or "unknown" response. Faster than CRL but creates a privacy concern — the CA sees every site you visit. OCSP soft-fail (no response = assume good) undermines security. | Current |
| OCSP Stapling | The server fetches its own OCSP response from the CA, caches it, and includes ("staples") it in the TLS handshake. The client doesn't need to contact the CA directly — solves the privacy problem and is faster. The stapled response is time-limited and CA-signed so it can't be forged. | Best practice |
| CRLite / OneCRL | Browser vendors (Mozilla, Google) aggregate CRL data and push compact filter structures directly to browsers via updates. Browsers can check revocation status offline without contacting CAs. Still being rolled out but growing in adoption. | Emerging |
A single cert covering one subdomain level: *.example.com covers www.example.com, api.example.com, but NOT sub.api.example.com. Convenient but a liability — one compromised key exposes all subdomains. Can't be used for the bare root domain (example.com) without also listing it as a SAN.
Cover multiple distinct domains in a single cert using Subject Alternative Names: example.com, example.net, otherdomain.io. Let's Encrypt issues these automatically. Modern certs use SANs exclusively — the CN field is largely deprecated for hostname matching.
Signed by the same key they certify — no CA involved. Fine for internal testing and private infrastructure where you control both endpoints. Browsers will show a security warning because there's no external trust anchor. For internal use, deploy your own private CA and distribute its root cert to your systems.
Used to sign executables, scripts, and packages rather than TLS endpoints. The OS or browser verifies the signature before running the code, confirming the publisher's identity and that the binary hasn't been tampered with. EV code signing certs have higher trust in Windows SmartScreen.
Normally only the server presents a certificate. With mTLS, both sides authenticate — the client also presents a cert the server verifies. Common in service mesh architectures (Istio, Linkerd), zero-trust networks, and API authentication where you need to verify machine identity, not just user identity.
A free, automated, open CA run by ISRG. Issues 90-day DV certificates via the ACME protocol — clients like Certbot or Caddy handle renewal automatically. 90-day validity encourages automation and limits exposure from compromised keys. Now issues ~half of all TLS certificates on the internet.
The cert's Not After date has passed. Server admin failed to renew. Fix: renew the cert and restart the web server. If you're using Let's Encrypt, set up auto-renewal with certbot renew --dry-run to test the cron job.
The domain in the certificate's Subject or SANs doesn't match the domain the browser connected to. Either the wrong cert is installed, the domain isn't covered by the cert's SANs, or you're accessing the server by IP. Check: openssl s_client -connect domain.com:443 | openssl x509 -noout -text | grep -A1 "Subject Alt"
The certificate chain doesn't lead to a trusted root CA in the browser's trust store. Common causes: self-signed cert, intermediate CA not installed on the server (browser only receives the leaf cert, not the full chain), or a private/internal CA whose root hasn't been distributed to clients.
Server is only sending the leaf cert without the intermediate(s). Browsers can sometimes fetch missing intermediates via AIA (Authority Information Access) but this is unreliable. Fix: configure your web server to serve the full chain. Check with: openssl s_client -connect domain.com:443 -showcerts
The CA has revoked the certificate before its expiry — usually because the private key was compromised or the cert was mis-issued. A revoked cert must be replaced immediately. Check revocation status: openssl ocsp -issuer chain.pem -cert server.pem -url http://ocsp.ca.com -resp_text
openssl s_client -connect example.com:443 </dev/null | openssl x509 -noout -text
Shows the full cert details — subject, SANs, issuer, validity, extensions, and signature algorithm.
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
Returns just notBefore and notAfter. Useful in monitoring scripts.
openssl s_client -connect example.com:443 -showcerts
Dumps all certificates sent by the server — leaf, intermediates, and sometimes root. Useful for diagnosing incomplete chain issues.
openssl verify -CAfile ca-chain.pem server.crt
Confirms the cert was signed by the CA in the bundle. Returns OK if the chain is valid. Essential before deploying a new cert to production.