S082 · TLS 1.3, PKI & Cert Lifecycle
The green padlock, demystified.
Module M10: Security · Session 82 of 130 · Track: SYS 🔐
What you'll be able to do after this session
- Explain TLS 1.3, PKI & Cert Lifecycle to a friend in one minute, out loud, no notes.
- Recognise it when you see it in real code / systems / papers.
- Complete the hands-on exercise at the end without looking up help.
Prerequisites
If you can't answer these in 30 seconds each, redo the linked session first:
Pre-read (skim before the session)
- 🎥 Intuition (5–15 min) · How HTTPS works — Fireship (100 seconds + follow-up) — quickest possible tour of the padlock.
- 🎥 Deep dive (30–60 min) · TLS 1.3 handshake explained — Computerphile — Dr Mike Pound walks through every message.
- 🎥 Hands-on demo (10–20 min) · Let's Encrypt with certbot — NetworkChuck — issue a real cert on a real server.
- 📖 Canonical article · Cloudflare — What happens in a TLS handshake? — the diagram you'll come back to.
- 📖 Book chapter / tutorial · Let's Encrypt — How it works — the ACME protocol in one page.
- 📖 Engineering blog · Cloudflare — Introducing TLS 1.3 — why TLS 1.3 dropped a round-trip and killed a lot of legacy crypto.
(a) Intuition · 5 min
The one-paragraph mental model. Why this concept exists, what problem it solves, and the analogy that makes it stick.
In one sentence: The green padlock, demystified.
TLS is what puts the "S" in HTTPS. The problem it solves is old-fashioned: I'm sending my credit card number over dozens of routers I don't control. Anyone in the middle can (a) read it, (b) modify it, or (c) pretend to be the bank. TLS gives us three properties in one bundle — confidentiality (encrypted), integrity (tamper-evident), and authentication (you're really talking to bank.com, not a coffee-shop wifi router).
The magic trick is that we don't need to have met the bank in person to trust them. Instead, we trust a small set of Certificate Authorities (CAs) — DigiCert, Let's Encrypt, GoDaddy, etc. — that your OS and browser ship with. The CA has previously verified that "the person controlling bank.com owns this public key". When your browser connects, the bank presents a certificate signed by the CA. Your browser checks the CA signature, and transitively trusts the bank. That whole chain-of-trust setup is called PKI — Public Key Infrastructure.
TLS 1.3 (the current version, 2018+) reduced the handshake to a single round-trip and threw out every crypto algorithm that had ever been broken (RC4, MD5, SHA-1, CBC modes, RSA key exchange). If you see TLS 1.0 or 1.1 anywhere in 2026, that's a bug.
Certificates have a lifecycle: issue → deploy → monitor expiry → renew → revoke if compromised. Every ops team has been paged at 3 AM because a cert expired and took the site down. Automation (certbot, cert-manager, ACM) is the fix.
Gotcha to carry forever: TLS proves you're talking to the domain on the cert. It does not prove the person behind the domain is honest.
hackerbank.comcan have a perfectly valid green padlock.
(b) Visual walkthrough · 15 min
Diagrams, worked examples, step-by-step visuals.
Here's the TLS 1.3 handshake — one round trip, and you're encrypted:
Worked example — the chain of trust. When you visit https://github.com:
| Level | Certificate | Signed by | Trusted because |
|---|---|---|---|
| Leaf | github.com | Sectigo ECC Domain Validation | its issuer is intermediate |
| Intermediate | Sectigo ECC DV CA | USERTrust ECC Cert Auth | its issuer is a root |
| Root | USERTrust ECC Cert Auth | self | hard-coded in your browser |
Your browser walks the chain from leaf to root. If the root is in the trust store, you're good.
Worked example 2 — why certs expire. A cert is a statement: "as of Jan 1, this key belongs to bank.com". If the private key later leaks and the CA never hears about it, the statement is a lie. Short expiries (Let's Encrypt: 90 days) bound the damage. There's a live proposal to move all public certs to 47 days by 2029 — automated renewal is now table stakes.
Common cert fields to know:
- CN / Subject Alt Name (SAN): the domain(s) the cert is valid for. Modern certs use SAN only.
- NotBefore / NotAfter: validity window.
- Extended Key Usage: what it's for (serverAuth, clientAuth, codeSigning).
- CRL / OCSP: revocation-check pointers.
(c) Hands-on · 20 min
Code you type and run. Not pseudo-code — real, runnable, copy-pasteable.
Two terminal exercises. First inspect a real cert; then issue one yourself locally with a mini-CA.
# ---------- 1. Inspect any live site's cert ----------
DOMAIN=github.com
echo | openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
# TLS version + cipher actually negotiated
echo | openssl s_client -connect ${DOMAIN}:443 -tls1_3 2>/dev/null | grep -E "Protocol|Cipher"
# ---------- 2. Build a tiny local PKI ----------
mkdir -p /tmp/mypki && cd /tmp/mypki
# (a) Create a Root CA
openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -subj "/CN=My Toy Root CA" -out rootCA.crt
# (b) Create a server key + CSR
openssl genrsa -out server.key 2048
openssl req -new -key server.key -subj "/CN=localhost" -out server.csr
# (c) Sign the CSR with our Root CA (adds SAN for localhost)
cat > san.ext <<EOF
subjectAltName=DNS:localhost,IP:127.0.0.1
EOF
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 30 -sha256 -extfile san.ext
# (d) Run an HTTPS server with the new cert
python3 -c "
import http.server, ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('server.crt', 'server.key')
srv = http.server.HTTPServer(('127.0.0.1', 8443), http.server.SimpleHTTPRequestHandler)
srv.socket = ctx.wrap_socket(srv.socket, server_side=True)
print('serving on https://127.0.0.1:8443')
srv.serve_forever()
" &
SERVER_PID=$!
sleep 1
# (e) Curl it — will FAIL until you tell curl about your CA
curl -sv https://127.0.0.1:8443/ 2>&1 | head -5 || true # SSL cert problem
curl -sv --cacert rootCA.crt https://127.0.0.1:8443/ 2>&1 | grep "SSL connection"
kill $SERVER_PIDObserve when you run it:
- Real GitHub cert shows Sectigo/USERTrust issuer chain and ~90-day validity window.
- Your negotiated protocol is
TLSv1.3and cipher likelyTLS_AES_128_GCM_SHA256. - The self-signed curl fails first — proving that browsers don't trust arbitrary certs.
- With
--cacert, curl now trusts your toy CA and completes the handshake. - The
server.crtis valid only forlocalhost/127.0.0.1(see SAN).
Try this modification: delete the SAN extension file and re-sign. Now curl (even with --cacert) fails with "certificate subject name does not match". That's the SAN rule biting you.
(d) Production reality · 10 min
How this shows up in real systems, gotchas, war stories, common bugs.
The Heartbleed bug (2014, CVE-2014-0160). OpenSSL let an attacker read 64 KB of server memory per malformed heartbeat request. Everyone on the internet had to rotate every private key. The lesson: even the crypto library itself is code, and code has bugs. This is why modern deployments favour battle-tested libraries (BoringSSL, LibreSSL, rustls) and why memory-safe languages for TLS stacks matter.
The 2018 Symantec distrust. Google and Mozilla removed trust in all Symantec-issued certs after finding misissuances. Millions of sites had to rotate. Lesson: your CA is a dependency, and dependencies can go bad.
Expired-cert outages that made the news: Microsoft Teams (Feb 2020), Cisco WebEx (2020), LinkedIn (2021), Ericsson (2018 — took down 32 M UK mobile users). The fix everyone converged on: automate renewal with certbot / cert-manager / ACM, monitor NotAfter with alerts 30/14/7 days out.
mTLS (mutual TLS). In microservices, you want both sides to prove identity — not just the server. Service meshes (Istio, Linkerd) auto-issue short-lived (~24h) certs to every pod and rotate them silently. This replaces Authorization: Bearer for internal traffic.
SNI leak. Even with TLS 1.3, the domain you're visiting is sent in plaintext in the ClientHello (SNI field). ECH (Encrypted Client Hello) fixes this — rolling out now on Cloudflare + Firefox.
How Cloudflare / Fastly handle it at scale. They terminate TLS at their edge (millions of certs stored on every POP), then re-encrypt to origin. This gives DDoS protection but means Cloudflare technically sees your plaintext — hence "Full (Strict)" mode where the origin also has a cert.
Rules teams live by: disable TLS 1.0/1.1, enable HSTS with preload, prefer ECDSA over RSA for speed, monitor Certificate Transparency logs (crt.sh) for rogue certs issued in your name, and never, ever put a private key in a git repo.
(e) Quiz + exercise · 10 min
- What three security properties does TLS provide, and which one does the certificate specifically deliver?
- How does TLS 1.3's handshake differ from TLS 1.2 in terms of round trips?
- What is a Certificate Authority and why do we trust root CAs at all?
- Give two reasons short-lived certificates (e.g., 90-day Let's Encrypt) are safer than 2-year certificates.
- Explain SNI and why it's a privacy leak even under TLS 1.3.
Stretch (connects to S081 — AuthN): mTLS uses client certificates instead of passwords for service-to-service AuthN. Sketch how a Kubernetes service mesh could issue per-pod certificates every 24 hours without any human intervention, and compare the revocation story vs a bcrypt-password system.
Explain-out-loud test
If you can't teach these 3 things to a friend without notes, redo the session:
- What is TLS 1.3, PKI & Cert Lifecycle? (one sentence, no jargon)
- When would you use it? (one concrete example)
- When would you NOT use it? (one anti-pattern)
What comes next
- Next session (S083): OWASP Top 10, Secrets Mgmt & Threat Modelling
- Previous (S081): AuthN vs AuthZ, Sessions & Password Storage
- Hub: The 6-Month Learning Plan
Part of a 130-session evergreen learning series. Session structure: (a) intuition · (b) visual walkthrough · (c) hands-on · (d) production reality · (e) quiz + exercise. Duration: 60 minutes.
More from M10 · Security
all modules →