Under the Hood
Networking

TLS: how the padlock works

What the 's' in https actually buys you — confidentiality, integrity, and authenticity as three separate guarantees — how asymmetric and symmetric crypto combine, Diffie-Hellman key exchange worked through with real numbers, forward secrecy, the TLS 1.3 one-round-trip handshake byte by byte, what a certificate really is and why your browser trusts it, SNI, session resumption and 0-RTT's replay caveat, and exactly what the padlock does and does not promise.

TLS: how the padlock works

You've seen the padlock in the address bar ten thousand times. You know it means "https, secure." But secure against what, and how? In the fetch lesson we said TLS "negotiates encryption" and runs a handshake after TCP. This lesson opens that box — because "the padlock" bundles three distinct guarantees, uses two entirely different kinds of cryptography to deliver them, and promises something narrower than most people assume.

Start from the threat. Your request to api.hisaab.measdev.me crosses a dozen networks you don't control: the coffee-shop wifi, the ISP, backbone routers, the data center's edge. Anyone on that path can, in principle, read every byte, change it in flight, or pretend to be the server. TLS (Transport Layer Security — the "S" in HTTPS) makes all three attacks fail. Over plain HTTP, all three succeed trivially.

The shape of the whole lesson

TLS has to solve one genuinely hard problem and then a few merely fiddly ones. The hard problem is the one worth slowing down for:

Two strangers, who have never met and share no secret, must agree on a secret key — while an attacker reads every single byte they exchange.

That sounds impossible. It isn't, and the trick that makes it work is called Diffie-Hellman. It gets its own section below, worked through with actual numbers, because everything else in TLS is scaffolding around it.

The rest follows from that:

  1. Why two kinds of crypto? Because the fast kind can't solve the key problem and the slow kind can't carry your data.
  2. How do we agree on a key in public? Diffie-Hellman.
  3. But agree with whom? DH alone gets you a secure channel to somebody — possibly the attacker. Certificates fix that.
  4. How is it all packed into one round trip? The TLS 1.3 handshake.

Three guarantees, not one

"Secure" is vague. TLS delivers three separate, nameable properties, and it's worth keeping them apart because they defend against different attacks:

  • Confidentiality — nobody on the path can read your data. This is encryption in the everyday sense. Without it, your Authorization: Bearer token is plaintext to every router it passes.
  • Integrity — nobody can modify your data undetected. Even encrypted data could in theory be tampered with; TLS attaches an authentication tag to every record so any flipped bit is caught and the connection dies. This stops an attacker from, say, changing the amount in a request even if they can't read it.
  • Authenticity — you're actually talking to the real server, not an impostor who intercepted the connection. This is the one people forget, and it's the one that makes the other two meaningful: encrypting a channel to an attacker who's impersonating your server protects nothing.

Keep authenticity separate in your head from the other two. Confidentiality and integrity come from the key exchange; authenticity comes from the certificate. They're delivered by different machinery, and mixing them up is the single most common reason this topic feels muddy.

Two kinds of crypto, and why TLS needs both

There are two families of cryptography, with opposite tradeoffs, and TLS uses each for exactly what it's good at.

Symmetric crypto uses one shared secret key to both encrypt and decrypt — same key both directions, like a physical lock where everyone with a copy of the key can both lock and unlock. It's fast: modern CPUs have hardware AES instructions and chew through gigabytes per second. The problem is right there in the name. Both sides need the same key, and you cannot send a key over a channel the attacker is reading, because then the attacker has the key too. A superb lock with an impossible key-delivery problem.

Asymmetric crypto (public-key) uses a pair of mathematically linked keys: a public key you hand to anyone, and a private key you never share. The pair is generated together and linked by math, but knowing the public one doesn't let you compute the private one. That asymmetry buys you two distinct powers:

  • Signing. The private key signs; the public key verifies. Only the holder of the private key could have produced a signature that verifies — this proves identity.
  • Key agreement. Two sides can combine their own private key with the other's public key and arrive at the same shared value, without ever transmitting it.

The catch: asymmetric operations are orders of magnitude slower than symmetric ones. Far too slow to encrypt a video stream, or a chat app's message traffic, or anything with volume.

So TLS combines them, and this is the central trick of the entire protocol:

Use slow asymmetric crypto once, at the start, to agree on a shared symmetric key and prove who you're talking to. Then use fast symmetric crypto for every byte of actual data.

Both jobs — the agreeing and the proving — happen in the handshake, and then asymmetric crypto is finished for the life of the connection. Everything after is AES.

Diffie-Hellman: agreeing on a secret in public

This is the piece worth understanding properly, because it's genuinely counterintuitive: two parties derive a shared secret while an eavesdropper watches every message, and the eavesdropper still can't compute it.

The intuition: mixing paint

Suppose you and I want a shared secret colour, but everything we mail each other gets photographed in transit.

We start by publicly agreeing on a common base colour — say yellow. Everyone knows it, including the attacker; that's fine. Then each of us privately picks a secret colour and keeps it to ourselves. I pick red, you pick blue.

I mix yellow + my red and mail you the result (orange). You mix yellow + your blue and mail me the result (green). The attacker photographs both orange and green.

Now I add my secret red to your green. You add your secret blue to my orange. We both end up holding yellow + red + blue — the identical colour. The attacker has yellow, orange, and green, but to reach yellow+red+blue they'd have to un-mix orange back into yellow and red. Mixing paint is easy; separating it is not.

That "easy forwards, hard backwards" property is the whole idea. Now here's the actual math that has it.

The actual math, with real numbers

Diffie-Hellman replaces paint mixing with modular exponentiation — raise a number to a power, then take the remainder after dividing by a prime. Easy to compute; brutally hard to reverse.

Two values are public and agreed up front, known to everyone including the attacker: a prime p and a base g (called the generator). Real TLS uses a 2048-bit prime or an elliptic curve; we'll use p = 23 and g = 5 so you can check the arithmetic yourself.

StepClientServerOn the wire (attacker sees)
1. Agree publiclyp = 23, g = 5p = 23, g = 5p = 23, g = 5
2. Pick a private secreta = 6 — never sentb = 15 — never sent
3. Compute a public shareA = 5⁶ mod 23 = 8B = 5¹⁵ mod 23 = 19
4. Swap the sharessends A = 8sends B = 198 and 19
5. Derive the secretB^a = 19⁶ mod 23 = 2A^b = 8¹⁵ mod 23 = 2

Both sides land on 2, and 2 never crossed the wire.

The reason it works is one line of algebra. The client computes (gᵇ)ᵃ and the server computes (gᵃ)ᵇ — and both of those are just gᵃᵇ. Exponents multiply the same way regardless of the order you apply them, so the two sides are computing literally the same number by two different routes. Each one supplies the exponent the other is missing, and neither ever has to reveal it.

Why the attacker is stuck

The eavesdropper has everything that crossed the wire: p = 23, g = 5, A = 8, B = 19. To compute the secret they need one of the private exponents — they'd have to solve 5ˣ mod 23 = 8 for x.

That's the discrete logarithm problem, and it's the hinge the whole thing hangs on. With p = 23 you can brute-force it by trying every exponent in a few seconds; that's why the toy numbers are only a teaching aid. With a 2048-bit prime, the search space is astronomically large and no efficient algorithm is known. Going forwards — computing 5⁶ mod 23 — is a handful of multiplications. Going backwards is infeasible. A one-way function is the entire foundation, exactly like the paint.

Turn the knobs yourself. Drag each side's private secret and watch the client's B^a and the server's A^b land on the same number every time — while only A and B cross the wire. Then hand the wire to the attacker and hit brute-force: with p = 23 they walk every exponent in a blink; bump the prime up and watch the same attack visibly grind. That widening gap is the whole security argument.

Public — everyone, including the attacker, knows these
prime p = 23 · generator g = 5
the article’s numbers — cracks instantly
Client
public A = 5^6 mod 23 = 8 sent →
derive B^a = 19^6 mod 23 =2
A = 8
B = 19
👁 Attacker on the wire
saw: p=23 g=5 A=8 B=19
never saw a or b — must solve 5^x mod 23 = 8 (the discrete log)
Server
public B = 5^15 mod 23 = 19 sent →
derive A^b = 8^15 mod 23 =2
client: 19^6 mod 23 = 2=server: 8^15 mod 23 = 2shared secret 2 · never sent — both routes compute gab

Drag either secret: the client's B^a and the server's A^b always land on the same number, because both are gab mod p. Only A and B ever cross the wire. Then let the attacker try to crack it.

What TLS actually uses today is ECDHE — Elliptic Curve Diffie-Hellman, Ephemeral. Elliptic curves swap "exponents mod a prime" for point arithmetic on a curve, which gets equivalent security from much smaller keys (a 256-bit curve ≈ a 3072-bit prime), so it's faster and the messages are shorter. The shape is identical: public parameters, private scalars, exchanged public points, both sides derive the same value. If you understand the modular version, you understand the curve version.

The "E" in ECDHE: forward secrecy

That trailing E — ephemeral — is not a detail. It means the private values a and b are generated fresh for every single connection and thrown away when it closes. They're never stored, never reused, never written to disk.

The payoff is forward secrecy, and it's a big one. Imagine an attacker records all your encrypted traffic today and stores it. Years later, they steal the server's private key. Can they go back and decrypt the recordings?

No — because the server's private key was never used to encrypt anything. It was only ever used to sign the handshake and prove identity. The keys that actually encrypted your data came from ephemeral DH values that existed for seconds in RAM and are long gone. Each connection's secret dies with it, so a future key compromise cannot retroactively unlock the past.

This is precisely why modern TLS abandoned the older design. In TLS 1.2's RSA key transport mode, the client picked the session key and encrypted it with the server's public key — meaning that one long-lived private key could decrypt every session ever recorded. Steal it once, read years of traffic. TLS 1.3 removed that mode from the specification entirely. Forward secrecy is now mandatory, not optional.

What Diffie-Hellman does not give you

Here's the gap, and it's the reason certificates exist at all.

DH gets you a shared secret with whoever was on the other end of the exchange. It does not tell you who that was. A passive eavesdropper is defeated — but an active attacker, one who can intercept and rewrite packets, can run two DH exchanges: one with you (pretending to be the server) and one with the server (pretending to be you). They sit in the middle holding both secrets, decrypting, reading, re-encrypting, and forwarding. Both ends see a perfectly encrypted connection. Both ends are wrong.

That's a man-in-the-middle attack, and DH has no defence against it whatsoever.

So the two mechanisms divide the labour cleanly, and this is the sentence to keep:

Diffie-Hellman gives you a secret channel. The certificate tells you who's at the other end of it. Neither is sufficient alone.

The handshake below is just those two things, interleaved and squeezed into one round trip.

The TLS 1.3 handshake, step by step

Here's the modern handshake. It runs after TCP's three-way handshake has completed, on top of the connection TCP opened. TLS 1.3 is designed to need only one round trip:

  Client                                                    Server
    │  (TCP already established underneath)                    │
    │                                                          │
    │  ClientHello                                             │
    │    • TLS version, cipher suites I support                │
    │    • my Diffie-Hellman KEY SHARE (a public value)        │
    │    • SNI: "api.hisaab.measdev.me"                        │
    ├─────────────────────────────────────────────────────────►
    │                                                          │
    │                                        ServerHello       │
    │                          • chosen cipher                 │
    │                          • server's DH KEY SHARE         │
    │                    ── both sides can now derive the ──   │
    │                    ── shared symmetric key here ──       │
    │                          {Certificate}   (chain)         │
    │                          {CertificateVerify} (signature) │
    │                          {Finished}                      │
    │◄─────────────────────────────────────────────────────────
    │                                                          │
    │  {Finished}                                              │
    │  {GET /groups ...}   ← application data, encrypted       │
    ├─────────────────────────────────────────────────────────►
    │                                                          │

Braces {...} mark messages already encrypted with the freshly derived key. Walk it:

  1. ClientHello carries the client's DH key share (A, in the notation above) immediately, along with the cipher options and SNI. This is the move that makes 1.3 one round trip — the client doesn't wait to be asked; it offers its half of the key exchange up front, guessing (correctly, almost always) which parameters the server will accept.
  2. ServerHello picks the cipher and sends the server's key share (B). At this instant both sides can independently derive the same shared secret, exactly as in the table above — the client has a and B, the server has b and A, and no eavesdropper ever saw the result. Everything from here on is encrypted, which is why the certificate itself arrives encrypted.
  3. Certificate and CertificateVerify deliver authenticity — the anti-MITM half. The server sends its certificate chain, then signs a hash of the entire handshake so far with its private key. Only the real holder of the private key matching the certificate's public key could produce that signature. Note what is signed: the handshake transcript, which includes both DH key shares. That's what welds the identity proof to this specific key exchange — a man-in-the-middle who substituted their own key share would need a valid signature over a transcript containing it, and can't produce one.
  4. Finished on both sides is a checksum over the whole handshake, so any tampering with the earlier plaintext hellos (cipher downgrade attempts, for instance) is caught before real data flows.

The division of labour, one line each:

MessageDelivers
ClientHello / ServerHello key sharesconfidentiality + integrity — the symmetric keys
Certificate + CertificateVerifyauthenticity — proof of who holds the private key
Finishedhandshake integrity — nothing was tampered with along the way

Count the trips: the client sends, the server responds, and the client can send its actual HTTP request in the very next message. One round trip of TLS setup, then data. If the server is 70ms away, that's ~70ms — stacked on top of the ~70ms TCP handshake underneath it, and then TCP slow start still has to ramp. Cold connections are expensive in layers.

TLS 1.2 needed two round trips. In the old flow the client's first message didn't carry a key share; the server had to respond, then the client sent its key material, then the server confirmed — a second full round trip before any data. So upgrading a server from TLS 1.2 to 1.3 literally removes ~70ms from every cold connection. That's not a micro-optimization; it's a round trip deleted from the critical path.

TLS 1.2TLS 1.3
Handshake round trips2 RTT1 RTT
Client key share sentafter ServerHelloin ClientHello
Forward secrecyoptional (RSA key transport allowed)mandatory — ephemeral DH only
Resumptionsession IDs/tickets, still ~1 RTTtickets, 0-RTT possible
Obsolete/weak ciphersmany still allowedstripped from the spec

What a certificate actually is

A certificate sounds mystical; it isn't. A certificate is a signed statement that says, essentially: "the public key inside this document belongs to api.hisaab.measdev.me, and I, the issuer, vouch for that." It bundles the server's public key, the domain name(s) it's valid for, an expiry date, and a digital signature from a Certificate Authority (CA).

That signature is the whole game. Anyone can generate a key pair and claim to be api.hisaab.measdev.me. What they can't do is get a trusted CA to sign a certificate for a domain they don't control — CAs only issue after verifying you own the domain (for Let's Encrypt, by making you place a specific file or DNS record only the owner could).

So when your browser gets the certificate, it doesn't trust it because it's pretty. It checks a chain of trust:

Your OS and browser ship with a trust store: a pre-installed list of a few hundred root CA public keys the vendors have vetted. The leaf certificate is signed by an intermediate, which chains up to one of those roots. Your browser verifies each signature in turn until it reaches a root it already trusts. Chain complete and valid, domain matches, not expired — padlock. Any broken link — the scary full-page warning. The trust is transitive: you trust the root, the root vouches for the intermediate, the intermediate vouches for the server.

Notice this closes the loop from the DH section. The certificate's public key is what verifies the CertificateVerify signature; the CA chain is what makes you believe that public key really belongs to this domain. That's the full path from "a root key shipped with your OS" to "this specific key exchange was performed by the real server."

SNI: why the server needs the name before HTTP exists

Here's a chicken-and-egg problem. One IP address (one server behind one nginx) can host many domains. During the handshake the server must send a certificate — but which one? The certificate is domain-specific, and the handshake happens before any HTTP, so the usual Host: header naming the site hasn't been sent yet (and couldn't be — it'd be inside encryption that isn't set up).

The fix is SNI (Server Name Indication): the client puts the target hostname in the ClientHello, in the clear, right at the start. Now the server knows which site you want and can present the matching certificate. Without SNI, virtual hosting over HTTPS would be impossible. The tradeoff: because SNI is sent before encryption exists, the hostname you're visiting is visible to the network even though everything after is encrypted. (Encrypted ClientHello is the evolving fix; classic SNI leaks the name.)

Resumption and 0-RTT: the fast path, with a catch

Doing the full handshake every time is wasteful when you talked to this server a minute ago. TLS 1.3 supports session resumption: after a successful handshake the server hands the client a session ticket (an encrypted blob of the session state). Next time, the client presents the ticket and both sides skip re-deriving everything from scratch — a cheaper handshake.

It goes further with 0-RTT ("zero round trip"): on resumption the client can send application data in its very first message, alongside the resumption attempt — no round-trip wait at all. Effectively free reconnects.

But 0-RTT has a real, sharp caveat you must respect:

Where the padlock lies

Now the part everyone gets wrong. The padlock proves confidentiality, integrity, and authenticity of the connection — an encrypted, untampered channel to the entity that legitimately controls the domain name you typed. That is all it proves.

It does not mean the site is honest, safe, or reputable. https://totally-legit-yourbank-login.com can have a perfect green padlock — because whoever registered that domain genuinely controls it and got a free certificate in thirty seconds. The padlock says "your bytes are going, privately and untampered, to the real owner of this domain." It says nothing about whether this domain is the one you meant, or whether its owner is a phisher. TLS authenticates the pipe, not the intent of whoever's on the other end. This is why phishing thrives on HTTPS: the lock is real, the encryption is real, and the site is still a scam. The padlock is a statement about the channel, never a character reference for the operator.

Go deeper

Check yourself

Answer out loud, as if an interviewer asked. If you hand-wave, reread that section.

  1. TLS uses both asymmetric and symmetric crypto. Which does the bulk data encryption and why, which is used only at the start and why, and what are the two distinct jobs the asymmetric part performs during the handshake?
  2. Walk Diffie-Hellman with p=23, g=5, client secret 6, server secret 15. What crosses the wire, what never does, and why can't an eavesdropper who saw everything compute the shared secret?
  3. Why is (g^b)^a the same as (g^a)^b, and why is that identity the entire reason the key exchange works?
  4. An attacker records your encrypted traffic today and steals the server's private key two years later. Can they decrypt the recording? Explain via ephemeral keys and forward secrecy, and say what was different about TLS 1.2's RSA key transport mode.
  5. Diffie-Hellman defeats a passive eavesdropper but not an active one. Describe the man-in-the-middle attack it permits, and explain exactly which handshake message stops it and how.
  6. What single design change lets TLS 1.3 complete its handshake in 1 RTT where TLS 1.2 needed 2? Point to the exact message and what it now carries.
  7. A certificate is "a signed statement." Signed by whom, binding what to what, and why can an attacker who fully controls their own server still not obtain a valid certificate for api.hisaab.measdev.me?
  8. Why does the client have to send the hostname in SNI in the clear at the very start of the handshake, rather than relying on the HTTP Host header like everything else? What does that leak?
  9. You enable 0-RTT to speed up reconnects and a POST that records a settlement occasionally executes twice. Explain the mechanism, and state the rule about which requests may travel as 0-RTT data.
  10. A phishing site shows a valid green padlock. Explain precisely what the padlock is and is not asserting, and why the lock being genuine does not contradict the site being a scam.