Public-key cryptography

Understand certificates and TLS

See how certificate chains bind public keys to names and why hostname, validity, chain, and trust-anchor verification must remain enabled.

A TLS certificate connects a public key to a name, like a domain, through a chain of signatures. A certificate authority signs the server’s certificate. A root that your system already trusts signs the CA’s certificate. Your operating system or browser ships with those roots preinstalled.

That chain is how your client trusts a public key it has never seen before. You can watch it with openssl:

openssl s_client -connect flaviocopes.com:443 -servername flaviocopes.com
# Certificate chain
#  0 s:CN=flaviocopes.com
#    i:C=US, O=Let's Encrypt, CN=E7
#  1 s:C=US, O=Let's Encrypt, CN=E7
#    i:C=US, O=Internet Security Research Group, CN=ISRG Root X2
# Verify return code: 0 (ok)

Read it bottom-up. ISRG Root X2 is in your trust store. It signed the Let’s Encrypt E7 intermediate. E7 signed the certificate for flaviocopes.com. Every link checks out, so the return code is 0.

During the handshake, the client sends the algorithms it supports, both sides run an ephemeral key agreement, and the server presents this chain. Then it proves it holds the private key by signing the handshake transcript. Only after that do encrypted application bytes flow.

What verification checks

The client checks several things: the hostname (the certificate names the domain you asked for), the validity period, the key usage, the chain itself, and that the chain ends at a trusted root. You can inspect those fields yourself:

openssl x509 -in cert.pem -noout -subject -dates -ext subjectAltName
# subject=CN=flaviocopes.com
# notBefore=Jun 12 08:21:33 2026 GMT
# notAfter=Sep 10 08:21:32 2026 GMT
# X509v3 Subject Alternative Name:
#     DNS:flaviocopes.com, DNS:www.flaviocopes.com

Every check answers a specific attack. Skip hostname verification and a perfectly valid certificate for attacker.dev satisfies a connection to your API.

Never disable verification

This incident repeats in every company. A developer hits a certificate error on staging. They set the “ignore certificate errors” flag to make it go away. Traffic is still encrypted, so it looks fine. But the client will now build that encrypted connection with anyone who presents any certificate.

Disabling verification turns encryption into a private conversation with an unknown party. And the flag ships to production, because these flags always do.

Private certificate authorities and local test certificates need deliberate trust configuration instead. Add your CA to the trust store, or pass it explicitly. In Node that is NODE_EXTRA_CA_CERTS=ca.pem. A global bypass turns one environment problem into a system-wide identity failure.

Certificates expire, so automate renewal and monitor the expiry date. An expired certificate is a full outage with a known date attached, which makes it the most avoidable outage there is.

Try this on your own: inspect a real certificate and note its names, validity period, key usage, issuer chain, and trusted root. Connect with the correct hostname and trust store. Then test a wrong hostname, an expired certificate, or an untrusted root, and confirm verification fails without you ever reaching for a global bypass.

Lesson completed