What HTTPS really is
HTTPS is not a protocol. It is HTTP carried inside a TLS session. The request line, the headers and the body are unchanged; TLS wraps them so the bytes on the wire cannot be read or altered by anyone in between.
That framing sets the boundary of the guarantee. TLS protects the channel. It says nothing about whether the server on the other end is honest, whether the application checks authorisation, or whether the data is safe once it reaches the backend. "We use HTTPS" answers exactly one question: can someone on the path read or modify this traffic?
The three guarantees, and what is missing
| Guarantee | What it means | Not covered |
|---|---|---|
| Confidentiality | Only the two endpoints can read the payload | Data at rest, logs, the server itself |
| Integrity | Altered bytes fail the authentication tag | A compromised endpoint can still lie |
| Authenticity | The certificate binds a domain to a public key | Whether the operator is trustworthy |
A padlock means the channel is sound. It does not mean the site is legitimate. Phishing sites hold valid certificates; that is exactly why the lock is not a safety badge.
The handshake in concrete terms
TLS 1.3 completes in one round trip:
- The client sends a ClientHello with supported cipher suites, a key share and the SNI hostname.
- The server replies with a ServerHello, its key share, the certificate chain and a signature over the handshake transcript.
- Both sides derive the same keys; the client verifies the chain and the signature.
- Application data flows, encrypted with an AEAD cipher such as AES-GCM or ChaCha20-Poly1305.
TLS 1.2 needs two round trips because key exchange and cipher negotiation are separate steps. That is why 1.3 is meaningfully faster on high-latency links, and why it is the default almost everywhere now.
What the certificate actually proves
A certificate is a signed statement: this public key belongs to this domain, and a certificate authority vouches for it. Validation checks several things, and each fails in a recognisable way.
- Chain of trust. The leaf must chain to a root the client trusts. A server that sends only the leaf works in browsers that cache intermediates and fails in Java, Go or older curl with "unable to get local issuer certificate". Always send the full chain.
- Name matching. The host must appear in the Subject Alternative Name extension; Common Name alone has been ignored by browsers for years. A mismatch yields
ERR_CERT_COMMON_NAME_INVALID. - Validity window. The current time must fall between notBefore and notAfter. A few minutes of clock skew is enough to break a freshly issued certificate.
- Revocation. Browsers use CRLite and OCSP stapling. In practice revocation checking is best-effort, which is why short certificate lifetimes matter more than revocation lists.
You can inspect all of it from a shell:
openssl s_client -connect example.com:443 -servername example.com -showcerts
Look at the Verify return code line, the certificate chain depth and the NotAfter date. If the chain shows only one certificate, the intermediate is missing.
Five myths worth retiring
- "Self-signed is insecure." The encryption is identical. What is missing is third-party identity assurance, so browsers warn. For service-to-service traffic under a private CA, privately issued certificates are normal practice.
- "TLS 1.0 is fine with a strong cipher." TLS 1.0 and 1.1 are deprecated by RFC 8996 and disabled in every major browser. Use 1.2 at minimum and 1.3 by preference.
- "Internal networks do not need TLS." East-west traffic crosses container networks, service meshes and inter-datacenter links. A compromised pod sniffs it as easily as an internet attacker.
- "The padlock means the site is safe." It means the channel is encrypted. Fraud sites buy certificates too.
- "HTTPS is slow." With TLS 1.3, session resumption and OCSP stapling you pay one extra round trip on a cold connection and effectively nothing afterwards.
Failure modes you will actually hit
Expired certificate. The most common outage, and the most embarrassing. Renewal automation fails silently and the first signal is a user screenshot. Alert at 30, 14 and 7 days to expiry, and treat a failed renewal as a production incident.
Incomplete chain. Works in Chrome, fails in Java and some mobile SDKs. Confirm the server sends the intermediate, not just the leaf.
SNI mismatch. One IP serving several domains must present the right certificate per SNI. A misconfigured default virtual host returns the wrong certificate for one of them.
HSTS preload mistakes. Once a domain is preloaded, browsers refuse plain HTTP for a long time, subdomains included. Roll out with a short max-age, verify every subdomain speaks HTTPS, then extend. Removing a preload entry takes months.
Clock skew. Containers with a broken NTP client fail validation with confusing errors. Check time sync before you debug the certificate.
One subtlety: 0-RTT and replay
TLS 1.3 allows a client to send early data on a resumed connection, cutting another round trip. The trade-off is that early data is replayable: an attacker who captures it can resend it. Never put non-idempotent state changes in 0-RTT. Browsers restrict it for exactly this reason, and servers should reject early data on write endpoints.
Operating it without drama
- Automate issuance and renewal. ACME with a real staging run, plus a documented fallback when the automation breaks. A renewal path that has never been tested is not automation.
- Pin protocol and cipher policy in code. Keep the allow-list in version control so a console edit cannot silently re-enable TLS 1.0.
- Monitor four numbers. Days to expiry, handshake failure rate, protocol distribution and chain depth. A sudden jump in handshake failures is almost always a certificate or middlebox change.
- Use mTLS for service-to-service. Server-only TLS authenticates the server to the client. When both sides need identity, mutual TLS with short-lived certificates from an internal CA is the standard answer.
- Keep application controls. TLS does not authenticate users, validate input or enforce authorisation. Those stay in the application.
Certificate types: DV, OV and EV
Certificates differ in how much identity verification the CA performs. Domain Validation (DV) proves control of the domain, usually through a DNS record or an HTTP challenge, and issues in minutes. Organization Validation (OV) also checks that the organization exists. Extended Validation (EV) adds a more rigorous legal review. All three provide the same encryption strength. EV no longer turns the address bar green in modern browsers, so for most sites DV with automation is the right trade-off; OV or EV matters when customers or contracts require verified identity.
Where TLS terminates, and why it matters
In most architectures TLS terminates at a load balancer or CDN edge, and the request continues to the application over plain HTTP inside the network. That is a legitimate design, but it moves the trust boundary: anyone who can observe the internal network sees the payload. If that is unacceptable, terminate at the edge and re-encrypt to the backend, or use mTLS inside the mesh.
The common bug here is losing the original scheme. After termination the application sees HTTP, so it may generate http:// redirects or set cookies without the Secure flag. Forward the original protocol in a header and, more importantly, configure the framework to trust only your own proxy, otherwise clients can spoof it.
HTTP/2, HTTP/3 and QUIC
TLS is independent of the HTTP version, but the combinations differ. HTTP/2 multiplexes many requests over one TLS connection, which removes head-of-line blocking at the HTTP layer but not at the TCP layer. HTTP/3 runs over QUIC, which builds TLS 1.3 into the transport and removes TCP head-of-line blocking entirely. Enabling HTTP/3 is usually a CDN switch. The operational catch is observability: some proxies and log pipelines still handle QUIC poorly, so keep HTTP/2 as a fallback and confirm your monitoring sees the real client protocol.
Diagnosing a certificate problem in five minutes
| Symptom | Likely cause | Check |
|---|---|---|
| Works in Chrome, fails in Java or Go | Incomplete chain | Chain depth from s_client |
| Expired or not yet valid | Renewal failure or clock skew | NotAfter, server time |
| Name mismatch on one of several domains | SNI or default virtual host | Test each hostname separately |
| Sudden handshake failures after a change | Protocol or cipher policy | Protocol distribution metric |
The takeaway
HTTPS protects data in transit between two endpoints that have proven their identity to each other. It is necessary and it is not sufficient. Treat the certificate lifecycle as production infrastructure, send the full chain, monitor expiry, and never let a green padlock stand in for application security.
Try it: AES encryption, Base64.