A certificate binds a public key to a verified identity, and a chain of trust up to a root CA is what makes HTTPS trustworthy. Understand the TLS handshake and issue your own certificate with a local CA.
An X.509 certificate is a signed statement: "this public key belongs to this identity (e.g. example.com), vouched for by this Certificate Authority, valid for this period." Because a trusted CA signed it, your browser can verify the signature and believe the binding — solving the trust problem from the previous lesson. The private key stays with the server; the certificate (public) is handed to every visitor.
An X.509 certificate contains (and the CA signs the whole thing):
Subject: CN=example.com (who this identifies)
Public Key: the server's public key
Issuer: the CA that vouches for it
Validity: notBefore / notAfter (e.g. 90 days)
SAN: example.com, www.example.com (the names it's valid for)
Signature: the CA's signature over all of the above
Your browser trusts it because it can verify the CA's signature AND
it already trusts that CA (next). The server keeps the matching
PRIVATE key secret.You do not trust every website's certificate directly — you trust a small set of root CAs shipped with your OS/browser. Those roots sign intermediate CAs, which sign server (leaf) certificates. Verification walks this chain from the server's cert up to a trusted root; if every signature is valid and nothing is expired or revoked, the leaf is trusted. Compromise anywhere up the chain breaks it, which is why root CAs are guarded intensely.
Trust flows DOWN a chain your device already anchors:
Root CA (in your OS/browser trust store; offline, guarded)
└─ signs Intermediate CA
└─ signs example.com (leaf) <- the cert the server presents
Verification walks UP: leaf -> intermediate -> root.
every signature valid? not expired? not revoked? name matches? -> trusted.
The server sends leaf + intermediates; your device supplies the root.
This is "Public Key Infrastructure" — the system of CAs, chains,
and trust stores that makes HTTPS work at internet scale.The handshake ties every prior lesson together. The client and server negotiate, the server proves its identity with its certificate and a signature, they perform an ephemeral key exchange to agree on a symmetric key, and then switch to fast authenticated symmetric encryption for the actual data. Authenticity (signatures), key exchange (asymmetric), and confidentiality (symmetric) all in one flow.
TLS 1.3 handshake (simplified):
1. ClientHello -> ciphers supported + client's ECDHE public key
2. ServerHello <- chosen cipher + server's ECDHE public key
+ CERTIFICATE (chain) + a SIGNATURE proving it holds
the matching private key
3. client verifies the cert chain (trust) + signature (authenticity)
4. both derive the same session key from ECDHE (key exchange, forward secret)
5. switch to AES-GCM with that key (fast symmetric, authenticated)
Signatures + asymmetric key exchange + symmetric encryption — the whole
course, in one connection setup.Doing it by hand demystifies PKI. With OpenSSL you can create a root CA, then issue a server certificate signed by it — exactly what a public CA does, minus the identity vetting. For local development, mkcert automates this and installs the CA into your trust store so browsers accept your local HTTPS. Never use a self-made CA for public sites; use an ACME CA (next lesson).
# 1) create your own root CA (private key + self-signed cert)
openssl genrsa -out ca.key 4096
openssl req -x509 -new -key ca.key -days 3650 -out ca.crt -subj "/CN=My Dev CA"
# 2) make a server key + CSR (certificate signing request)
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=app.local"
# 3) the CA signs the CSR -> a server certificate
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -days 90 -out server.crt
# inspect what you made:
openssl x509 -in server.crt -noout -text | grep -A1 "Subject:\|Validity"
# for local dev, 'mkcert app.local' does all this + trusts the CA for you.