TL;DR
- HTTPS = HTTP over TLS → encryption, integrity, and authentication.
- In TLS 1.3 the handshake is: ClientHello → ServerHello + Certificate → ECDHE key exchange → Finished → 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 (h3over 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 |