caduh

How SSL/TLS Works in 60 Seconds — the HTTPS handshake demystified

2 min read

Demystify the TLS handshake—ClientHello, ServerHello, certificates, ECDHE key exchange, session keys—and why HTTPS protects confidentiality, integrity, and authenticity.

TL;DR

  • HTTPS = HTTP over TLSencryption, integrity, and authentication.
  • In TLS 1.3 the handshake is: ClientHelloServerHello + CertificateECDHE key exchangeFinished → encrypted HTTP.
  • Certificates must match the hostname, be unexpired, and chain to a trusted CA. Prefer OCSP stapling.
  • Use TLS 1.3, enable HTTP/2 or HTTP/3, enforce HSTS, and auto‑renew certs (e.g., Let’s Encrypt).
  • Avoid mixed content; send cookies with Secure and usually SameSite=None when cross‑site is required.

Why HTTPS is essential

  • Confidentiality: attackers on the network can’t read traffic.
  • Integrity: tampering is detected (AEAD ciphers like AES‑GCM/ChaCha20‑Poly1305).
  • Authentication: the server proves its identity with a certificate.
  • Modern features: HTTP/2 and HTTP/3 are effectively HTTPS‑only, often faster than HTTP/1.1 over TCP.
  • Trust & SEO: browsers flag non‑HTTPS as “Not secure,” and search engines prefer HTTPS.

The handshake in one screen (TLS 1.3)

Client ───────────────────────────────► Server
  ClientHello {
    SNI=app.example.com, ALPN=[h2,h3], key_share=ECDHE, supported_versions=[1.3,1.2]
  }

Server ───────────────────────────────► Client
  ServerHello { chosen_version=1.3, cipher=TLS_AES_128_GCM_SHA256, key_share=ECDHE }
  Certificate { chain: leaf → intermediate(s) → root }
  (OCSP Staple + SCTs if provided)
  CertificateVerify
  Finished

# both sides derive handshake secrets → application secrets (session keys)

Client ───────────────────────────────► Server
  Finished

# Now application data (HTTP/2 or HTTP/3) flows encrypted

Notes

  • ECDHE provides Perfect Forward Secrecy (past traffic stays safe even if keys leak later).
  • TLS 1.3 is 1‑RTT; session resumption can be 0‑RTT (beware replay risks).

What gets verified

  • The cert’s SAN includes the requested hostname (SNI).
  • The cert isn’t expired and is properly chained to a trusted root.
  • The server proves it owns the private key (CertificateVerify).
  • Optional: OCSP stapling provides revocation status; CT/SCTs aid transparency.

Minimal production checklist

  • ✅ Prefer TLS 1.3 (allow 1.2 as fallback); disable 1.1/1.0.
  • ✅ Ciphers: ECDHE + AES_GCM or ChaCha20‑Poly1305 (AEAD).
  • ✅ Redirect HTTP→HTTPS, enable HSTS (after testing): Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • ✅ Turn on HTTP/2 (ALPN h2) or HTTP/3 (h3 over QUIC).
  • ✅ Enable OCSP stapling and session resumption (tickets/PSK).
  • ✅ Use ECDSA certs when client base supports it (smaller, faster); otherwise RSA ≥ 2048‑bit.
  • Automate renewals (ACME/Let’s Encrypt) and monitor expiry.

Quick tools

  • Inspect handshake:
    openssl s_client -connect app.example.com:443 -servername app.example.com -tls1_3 -alpn h2
    
  • Verbose request to see protocol/ALPN:
    curl -Iv https://app.example.com
    

Common errors & fast fixes

| Symptom | Likely cause | Fix | |---|---|---| | NET::ERR_CERT_COMMON_NAME_INVALID | Hostname doesn’t match SAN | Reissue cert with correct SANs; ensure SNI is configured | | “Self‑signed certificate” in prod | Chain not trusted | Use a public CA; install full chain | | Mixed content blocked | Page loads HTTP resources | Make all asset URLs HTTPS or use upgrade-insecure-requests | | “Protocol version” alert | Old client vs. server settings | Support TLS 1.2+; keep 1.3 on; drop 1.0/1.1 | | Intermittent trust errors | Missing OCSP stapling or bad chain at CDN node | Enable stapling; deploy full chain to all edges |