Metadata Card
- Prerequisites: Chapter 1 Cryptography Basics (symmetric/asymmetric encryption, hashing)
- Estimated time: 50 minutes
- Core difficulty: Advanced
- Completion mark: Can explain the structure of an X.509 certificate, generate a self-signed certificate with openssl, understand the certificate chain verification process
Your Progress
You've learned to use asymmetric encryption formations to protect communications—you have a public rune, the other party has a private rune, and encrypted magical letters can only be decrypted by the private rune holder.
But you've encountered a new problem: how do you know that the public rune in your hand really belongs to "the Grey Tower's Portal Guard," and not some dark mage impersonating the guard?
At the end of the last chapter we said "the key distribution problem" was solved by asymmetric encryption, but that only transformed the problem from "how to securely deliver the key" to "how to securely obtain the other party's public rune." This is a trust problem, and trust in the magical world requires an infrastructure—a rune certification system.
Your Task
Understand how PKI (Public Key Infrastructure) solves the "public key ownership" problem. You'll master the structure of X.509 certificates, certificate chain verification mechanisms, the CA trust model, and modern practices like ACME automated issuance and Certificate Transparency.
Chapter Layers
- Required: X.509 certificate structure, certificate chains, self-signed certificate hands-on, openssl
- Optional: ACME protocol flow, CRL & OCSP
- Advanced: Certificate Transparency Merkle Tree proofs
Breaking Ground · Tracing the Origin
Problem: You receive a letter claiming to be from "the Border Fortress messenger," with the other party's public key attached. How do you know this is really the fortress's public key?
The intuitive approach: find a third party that everyone trusts to vouch for it. This third party is called a Certificate Authority (CA).
The CA's job:
- Verify the applicant's identity (are you who you claim to be?)
- Issue a digital certificate that binds a "public key" to an "identity"
- When someone questions the ownership of a public key, the CA can verify the certificate
What does an X.509 certificate look like?
X.509 is the standard defining certificate format (ITU-T standard, RFC 5280). An X.509 certificate includes:
Certificate (v3 format):
├── Version (currently v3)
├── Serial Number (uniquely assigned by CA)
├── Signature Algorithm (e.g., sha256WithRSAEncryption)
├── Issuer (the CA that issued this certificate)
├── Validity
│ ├── notBefore: Effective date
│ └── notAfter: Expiration date
├── Subject (the certificate holder's name)
├── Subject Public Key Info
│ ├── Algorithm (e.g., RSA/ECC)
│ └── Public key value
├── Extensions (v3 additions)
│ ├── Subject Alternative Name (SAN, modern web uses this instead of Subject)
│ ├── Key Usage (digitalSignature, keyEncipherment, etc.)
│ ├── Extended Key Usage (serverAuth, clientAuth)
│ ├── Basic Constraints (whether it's a CA certificate)
│ └── ... more extensions
└── Signature (CA's signature, hashes the entire certificate and signs with CA's private key)View a real website certificate with openssl:
openssl s_client -connect github.com:443 -servername github.com </dev/null 2>/dev/null \
| openssl x509 -text -noout | head -60You'll see output similar to:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
04:...
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
Validity
Not Before: Mar 15 00:00:00 2024 GMT
Not After : Mar 20 23:59:59 2025 GMT
Subject: CN=github.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
...
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:github.com, DNS:www.github.comCertificate Chains: Multi-Layer Trust
Who issues the CA's certificate? A higher-level CA. This forms a chain:
Root CA (self-signed)
└── Intermediate CA1 (issued by root CA)
└── Intermediate CA2 (issued by intermediate CA1)
└── End-entity certificate (issued by intermediate CA2, e.g., github.com)The root CA's certificate is self-signed—it issues its own certificate. Browsers and operating systems have a built-in set of root certificates (about 100-150), which are the trust anchors.
The verification process is chain-based:
# Pseudocode: certificate chain verification
def verify_cert_chain(leaf_cert, intermediate_certs, root_store):
"""
Verify a certificate chain:
1. Start from the leaf certificate
2. Find the CA certificate that issued it
3. Verify the leaf certificate's signature with the CA's public key
4. Recursively verify the CA certificate until reaching a root certificate
"""
cert = leaf_cert
while not cert.is_self_signed():
issuer = find_issuer_cert(cert, intermediate_certs, root_store)
if issuer is None:
return False # Can't find issuer
# Verify current certificate's signature with issuer's public key
if not verify_signature(cert, issuer.public_key):
return False
# Check if certificate is within validity period
if not cert.is_within_validity_period():
return False
# Check if certificate is revoked
if is_revoked(cert):
return False
cert = issuer # Recurse upward
# Finally: verify root certificate is in the trust store
return cert in root_storeMaking a Self-Signed Certificate
To understand the certificate generation process, sign one on your own development machine. It's like an outpost carving its own seal—outsiders may not recognize it, but at least you can verify identity with headquarters:
# 1. Generate private key
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \
-out mykey.pem
# 2. Create Certificate Signing Request (CSR)
openssl req -new -key mykey.pem -out mycsr.csr \
-subj "/CN=myapp.local/O=MyOrg/C=CN" \
-addext "subjectAltName=DNS:myapp.local,DNS:localhost,IP:127.0.0.1"
# 3. Self-sign (issue certificate in CA role)
openssl x509 -req -in mycsr.csr -signkey mykey.pem \
-out mycert.pem -days 365 \
-extfile <(echo "subjectAltName=DNS:myapp.local,DNS:localhost") \
-sha256
# 4. View certificate content
openssl x509 -in mycert.pem -text -nooutThis self-signed certificate can be used directly for development environment TLS. Start a simple Python HTTPS server:
# server.py
import http.server
import ssl
server = http.server.HTTPServer(('0.0.0.0', 8443), http.server.SimpleHTTPRequestHandler)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain('mycert.pem', 'mykey.pem')
server.socket = context.wrap_socket(server.socket, server_side=True)
print("HTTPS server running at https://localhost:8443")
server.serve_forever()When you visit https://localhost:8443, the browser will warn "certificate not trusted"—this is correct, because this certificate wasn't issued by a CA trusted by the browser.
CA Certificate Issuance Flow (ACME)
In a production environment, you wouldn't self-sign. Instead, you'd get a certificate from Let's Encrypt (a free CA). Let's Encrypt uses the ACME (Automatic Certificate Management Environment) protocol to automatically issue certificates.
The core ACME flow (using HTTP-01 validation as an example):
1. Client (your server) generates a key pair and CSR
2. Client requests certificate issuance from the ACME server
3. Server gives a challenge: place a specific token file at a specific path
4. Client creates the file in the website root: /.well-known/acme-challenge/<token>
5. ACME server accesses that path via HTTP to verify domain control
6. Verification passes, ACME server issues the certificate
7. Client downloads the certificate and intermediate CA certificateOne-liner with certbot:
# Install certbot (Ubuntu)
sudo apt install certbot python3-certbot-nginx
# Issue certificate
sudo certbot --nginx -d example.com -d www.example.com
# Certificates go to /etc/letsencrypt/live/example.com/
# Contains: fullchain.pem (full chain) + privkey.pem (private key)Let's Encrypt certificates are valid for 90 days. This may seem inconvenient, but it's by design—short validity reduces the complexity of revocation and encourages automation.
Revocation Checking
Certificates may need to be invalidated before expiration due to private key compromise or identity changes. There are two revocation checking methods:
- CRL (Certificate Revocation List): The CA periodically publishes a list of serial numbers of revoked certificates. Clients download and cache it.
- OCSP (Online Certificate Status Protocol): Real-time query; the client asks the CA's OCSP server whether a specific certificate is still valid.
OCSP is more real-time than CRL, but has a privacy issue—the CA can know which sites you're visiting. OCSP Stapling solves this: the server periodically fetches OCSP responses from the CA and includes them in the TLS handshake.
Certificate Transparency (CT)
In 2011, an attacker impersonated a CA (DigiNotar) to issue fake certificates for Google, used for man-in-the-middle attacks against Iranian users. This incident exposed a fundamental flaw in PKI: any CA can issue certificates for any domain, with no global visibility.
CT's solution: all certificates issued by CAs must be recorded in public logs, auditable by anyone.
Certificate Transparency log (Merkle Tree structure):
├── Root hash (current log state)
├── Certificate entry 1 (with signed timestamp)
├── Certificate entry 2
├── ...
└── Certificate entry N
When each certificate is issued, the CA submits it to the log
The log returns a Signed Certificate Timestamp (SCT)
SCTs are embedded in certificates or transmitted via TLS extensions
Browsers require at least 2-3 different SCTs per certificateSince 2018, Chrome requires all newly issued SSL/TLS certificates to have embedded SCTs; otherwise they are treated as untrusted.
Common Pitfalls
- Wildcard certificate misuse.
*.example.comprotectswww.example.combut notexample.com, and certainly notother.com. Modern practice uses multi-SAN certificates. - Using self-signed certificates in production. Self-signed certificates are only for development and internal testing. Production should use a public or internal CA.
- Ignoring certificate renewal. Let's Encrypt's 90-day validity requires automated renewal. Use systemd timers or cron.
- Incomplete certificate chain. Some servers only send the leaf certificate without intermediate CA certificates. Browsers may need to download intermediates (increasing handshake latency; some older clients don't support this).
- Overly permissive private key permissions. Private key files should have 600 permissions, readable only by the web server user.
- Using Subject instead of SAN. Since Chrome 58, browsers only look at Subject Alternative Name for site identity; they no longer match Common Name (CN).
Pass Challenges
- Warm-up: Use openssl to connect to
google.com:443, extract and print the server certificate's Issuer and Subject. Then write a one-liner to extract the certificate's validity period. - Challenge: Create a simple local HTTPS service. First generate a CA root certificate (self-signed), then use it to issue a server certificate. Configure nginx or a Python HTTP server to use this certificate and make your browser trust your CA.
- Troubleshoot: A colleague says "My HTTPS site works fine with curl, but the browser reports NET::ERR_CERT_COMMON_NAME_INVALID." Diagnose and fix this issue.
- Observe: Visit
https://crt.shand search for your domain (if you have one) to see which certificates are recorded in CT logs.
Traveler's Notes
- PKI solves the "who does this public key belong to" trust problem, centered on X.509 certificates and CA hierarchy
- An X.509 certificate contains identity info, public key, validity period, and issuer's signature
- Certificate chains go from root CA to intermediate CA to leaf certificate; root certs are built into OS/browsers
- ACME automation (Let's Encrypt) eliminates manual certificate lifecycle management
- Certificate Transparency makes all certificates publicly visible, preventing malicious CAs from operating in the dark
Next Stop Preview
You have encryption capabilities and a certificate mechanism to verify the other party's identity. But who is the other party—how is identity confirmed? Does holding a private key count as "authentication"? Next chapter, we dissect the authentication and authorization system.