Core CS · Computer Networks
Three guarantees, and only one of them is encryption
TLS is not a secret code bolted onto HTTP. It is a thin layer under it that proves who the server is, agrees a key that neither side ever sends, and only then starts encrypting. Take away the proof and the encryption protects nothing at all.
Step a handshake message by message and watch the wire go dark →01 The idea
A private conversation needs three things, not one
Every packet you send crosses machines you do not own. The café router, your college’s NAT box, three or four ISP routers, and whatever sits in front of the server. Any one of them can read your bytes, change your bytes, or answer in the server’s place. So a connection over an untrusted network has to solve three separate problems, and it is worth being able to name all three, because candidates who name only the first one get caught by the follow-up.
The first is confidentiality: nobody in the middle can read what you sent. The mechanism is symmetric encryption of every record with a shared session key. The second is integrity: nobody in the middle can change what you sent without being caught. Encryption alone does not give you this, which surprises people. A ciphertext you cannot read is still a ciphertext you can flip bits in, and the receiver would decrypt it to something different and never know. The mechanism is a message authentication code, a short tag computed from the data and the key; change one bit of the record and the tag no longer matches, so the receiver throws the record away.
The third is authentication, and it is the one this lesson keeps coming back to: you are talking to the machine you meant to talk to and not to an impostor. The mechanism is a certificate, signed by an authority your machine already trusts. Say plainly what happens without it. If you encrypt to whoever answers, an attacker who intercepts the connection completes the handshake with you himself, opens a second connection to the real server, and forwards everything between the two. Both halves are properly encrypted. Both halves have valid integrity tags. He reads and edits every byte. Encryption without authentication is not weak security, it is close to no security, because it protects a conversation with the attacker.
Now the placement in the stack, which is the other half of the idea. TLS is not an application protocol. It is a layer that sits between the transport layer and the application: TCP hands it a byte stream, it hands the application a byte stream that happens to be private, and the application protocol above it does not change by one character. That is why HTTPS is exactly HTTP, with the same methods, the same status codes and the same headers, carried inside TLS on port 443 instead of in the clear on port 80. It is also why SMTP, IMAP, POP3, FTP, LDAP and DNS all have TLS variants without anybody redesigning their grammar. You wrap the pipe; you do not rewrite what flows through it.
02 Worked example
One browser, one server, one handshake
A browser opens https://www.example.com/. TCP has already finished its own three-way handshake to port 443, so a byte stream exists and nothing on it is private yet. What follows is a TLS 1.2 handshake compressed to five moves, and it is the same connection for the rest of the lesson: the message table in section 03 expands it row by row, the console in section 04 lets you step it, and every claim in the cheat sheet is checked against it. Read left to right, and watch which moves are readable by anyone on the path.
Two things in that sequence do most of the work, and node 3 is both of them. Take the key first. The word agreement is doing something specific and it is the point students most often get wrong. Nobody generates a session key and sends it. Each side picks a private value, publishes a value derived from it, and then does one calculation that turns its own private value plus the other side’s public value into a shared secret. Both calculations land on the same number. An observer who recorded every single byte of the handshake holds two public values and cannot get from them to that number. The session key is computed twice and transmitted zero times, which is why recording the traffic does not help you.
The second thing is the signature in node 3, and it is what stops the whole scheme from being a polite conversation with an attacker. Notice that a certificate on its own proves nothing. It is a public document; anyone can connect to www.example.com, take a copy of its certificate, and present that copy to you. What an impostor cannot do is produce a signature that verifies against the public key inside it, because that needs the private key. So the server signs its Diffie-Hellman public value, together with both random values from node 1, using the private key that matches the certificate. The client verifies that signature with the public key it just received. Only then does it believe anything.
Both random values are in that signature for a reason worth stating, because it is the difference between an answer and a memorised one. If the server signed only its own key share, an attacker could record a signed message from a real connection today and replay it in a fake connection tomorrow. Including the client’s fresh random makes the signature specific to this connection, so a recorded one is useless. That is the same reason the client random exists at all.
Finally, look at where the encryption starts. Moves 1, 2 and 3 are entirely in the clear. Anybody on the path can read which site you are contacting, which cipher suites your browser offers, and the full certificate the server sent back. The connection only goes dark at move 4. That is the ordering to remember for TLS 1.2, and it is precisely the part TLS 1.3 rearranges.
03 Mechanics
Every message, every guarantee, and every version that is now dead
Five tables, in the order the questions come. First the handshake in full, because "walk me through the TLS handshake" is asked directly and the follow-up is always which of those was readable. The last column is the one to study. Read down it and find the row where it flips.
| # | Message | Direction | What it carries | On the wire |
|---|---|---|---|---|
| 1 | ClientHello | client to server | Highest version supported, a 32-byte client_random, the list of cipher suites it will accept, and extensions including SNI, the hostname being requested. | cleartext |
| 2 | ServerHello | server to client | The one version and the one cipher suite the server chose from those lists, plus a 32-byte server_random. | cleartext |
| 3 | Certificate | server to client | The server’s certificate and the intermediate certificates above it. Public key inside. No private key, here or anywhere else on the wire. | cleartext |
| 4 | ServerKeyExchange | server to client | The server’s ephemeral Diffie-Hellman public value, signed with the certificate’s private key over both randoms and that value. This message is what authenticates the server. | cleartext, but signed |
| 5 | ServerHelloDone | server to client | No fields. It marks the end of the server’s flight, which completes round trip one. | cleartext |
| 6 | ClientKeyExchange | client to server | The client’s ephemeral Diffie-Hellman public value. Both sides derive the shared secret at this point, and the secret is in no field of any message. | cleartext |
| 7 | ChangeCipherSpec | client to server | A single byte meaning "everything you get from me after this is under the new keys". The last thing the client sends in the clear. | cleartext |
| 8 | Finished | client to server | A value computed from a hash of every handshake message so far, keyed with the master secret. The first encrypted message of the connection. | ENCRYPTED |
| 9 | ChangeCipherSpec | server to client | The same one-byte switch in the other direction. | cleartext |
| 10 | Finished | server to client | The server’s transcript check. This completes round trip two, and the handshake is over. | ENCRYPTED |
| Two round trips, ten messages, and not one byte of your request has moved yet. On top of the TCP handshake’s own round trip, that is three round trips before the server sees GET /. This is the entire reason TLS 1.3 exists and the entire reason real systems reuse connections instead of opening a fresh one per request. | ||||
| 11 | Application data | client to server | GET / HTTP/1.1 and its headers, unchanged, inside an AES-GCM record with a 16-byte tag. | ENCRYPTED |
| 12 | Application data | server to client | The HTTP response, under a different key from the request: the two directions get separate write keys from the same master secret. | ENCRYPTED |
Why the switch happens at message 8 and not earlier. The keys do not exist before message 6, so nothing before message 6 could have been encrypted. But that leaves an obvious hole: messages 1 to 7 were readable, so they were also editable. An attacker on the path could have deleted the strong cipher suites from the ClientHello and left only a weak one, and both machines would have negotiated the weak suite believing it was the best on offer. Finished closes that hole. Each side hashes the complete transcript of every handshake message it sent and received, and puts the result, keyed with the master secret, into its Finished. If the two transcripts differ by a single byte the check fails and the connection is torn down before any data moves. The handshake is in the clear, but it is not unprotected.
And why the slow cryptography is confined to the setup. The numbers make the design obvious. AES-128-GCM with the AES instructions present on every modern CPU processes on the order of a gigabyte per second per core. One RSA-2048 private-key operation takes on the order of a millisecond. Encrypting a 2 MB page with public-key operations is not slightly slower, it is not something you would attempt. So TLS spends its asymmetric budget on two things and stops: one signature to authenticate the server, and one key agreement. From message 8 onwards everything is symmetric, and the connection runs at line rate. When somebody asks why TLS uses both kinds of cryptography, that pair of sentences is the answer.
Now the three guarantees, each pinned to the mechanism that supplies it and the message it is delivered in. The last column is what an attacker does when that one row is missing, and it is the column that turns a memorised list into an answer.
| Guarantee | Mechanism | Delivered at | Without it, the attacker |
|---|---|---|---|
| Confidentiality | symmetric encryption of every record with the session key | Each direction from its own Finished, messages 8 and 10; keys derived at message 6. | Reads your password, your session cookie and your bank balance straight off the wire. |
| Integrity | an authentication tag on every record, plus the transcript hash inside Finished | Tag on every encrypted record; transcript checked in messages 8 and 10. | edits ciphertext in flight and downgrades your cipher list without either side noticing |
| Authentication | a certificate chain, plus a signature made with the matching private key over this connection’s values | Messages 3 and 4 together. Neither one alone is enough. | completes the handshake as the server and encrypts everything with you instead of with the site |
| Forward secrecy | the Diffie-Hellman private values are ephemeral and are destroyed when the connection ends | Message 6, and it costs nothing extra. | Records your traffic today, steals the server’s private key next year, and decrypts the recording. |
Forward secrecy, and the one honest exception to "the key is never sent". Older TLS also allowed RSA key transport, where the client generated the pre-master secret itself, encrypted it with the public key from the certificate, and sent it across. That version really did put key material on the wire, protected by a key that lives on the server for years. Record the traffic, obtain that private key at any point in the future, and every past session opens. Ephemeral Diffie-Hellman has no such value: the private halves are thrown away when the connection closes and cannot be recovered from anything. This is why TLS 1.3 removed RSA key transport entirely, and why the honest form of the claim is: in the ephemeral key exchange that both versions use in practice, and the only one TLS 1.3 permits, nothing that crosses the wire is the key.
Reading a cipher suite name. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 is four decisions written out. ECDHE is the key agreement, elliptic-curve Diffie-Hellman, ephemeral, so this connection has forward secrecy. RSA is the signature algorithm used to authenticate, which tells you what kind of key is in the certificate. AES_128_GCM is the bulk cipher, an AEAD mode that encrypts and produces the integrity tag in one pass. SHA256 is the hash for the key derivation. TLS 1.3 shortens the whole thing to TLS_AES_128_GCM_SHA256, because key agreement and authentication are negotiated separately in extensions and are no longer part of the suite name.
The certificate is the second half of the topic and the half that generates real support tickets. A certificate binds a set of hostnames to a public key, and it is trusted because of a chain: your server’s leaf certificate is signed by an intermediate CA, the intermediate is signed by a root CA, and the root is self-signed and already present in your operating system’s or browser’s trust store because it was shipped with it. The server sends the leaf and the intermediates; it does not send the root, because a root you receive from a stranger proves nothing and a root you already trust does not need sending. Here is what a browser then checks, and what it says when each check fails.
| What the browser says | What actually failed | What fixes it |
|---|---|---|
ERR_CERT_DATE_INVALID | Today is outside the notBefore to notAfter window written inside the certificate. Usually expiry; occasionally the client’s own clock is wrong. | Reissue and redeploy, then automate the renewal so it cannot happen twice. |
ERR_CERT_COMMON_NAME_INVALID | The hostname the user typed is not in the certificate’s Subject Alternative Name list. Modern browsers ignore the old Common Name field entirely and read only the SAN list. | Reissue with every name the site is served under, wildcards included. |
ERR_CERT_AUTHORITY_INVALID | The chain does not reach a root in this client’s trust store. Either the certificate is self-signed, or the server sent the leaf and forgot the intermediates. | Serve the full chain. If the CA really is private, install its root on the client deliberately. |
ERR_CERT_REVOKED | The CA has published that this certificate is no longer valid, which almost always means the private key leaked. | Reissue with a new key pair. Revoking without changing the key achieves nothing, because the leaked key still matches. |
| Revocation is the weak one, and interviewers know it. Certificate revocation lists grew large, and browsers query the Online Certificate Status Protocol in a way that fails open, so an attacker who can block the check can also make it pass. The practical answers are OCSP stapling, where the server fetches a signed freshness statement and attaches it to the handshake, and short certificate lifetimes, which shrink the window revocation would have had to cover. Let’s Encrypt issues 90-day certificates for exactly this reason. | ||
Versions next, and this is a table to get exactly right, because a candidate who says "we use SSL" has already told the interviewer something. SSL was the Netscape original; TLS is the IETF standardisation of it, and every version in production use today is TLS.
| Version | Year | Status | Round trips before the first request | Why |
|---|---|---|---|---|
| SSL 2.0 | 1995 | prohibited, RFC 6176 | — | The handshake itself was not protected, so it could be downgraded silently. |
| SSL 3.0 | 1996 | deprecated, RFC 7568 | 2 | Broken by POODLE in 2014, which exploited its CBC padding. |
| TLS 1.0 | 1999 | deprecated, RFC 8996 | 2 | Still SSL 3.0’s shape underneath. Browsers removed it in 2020. |
| TLS 1.1 | 2006 | deprecated, RFC 8996 | 2 | Fixed one CBC problem and was overtaken before it was ever widely deployed. |
| TLS 1.2 | 2008 | widely deployed, still allowed | 2 | First version with AEAD suites and SHA-256. Keeps a lot of legacy options that have to be configured off. |
| TLS 1.3 | 2018 | current, RFC 8446 | 1 | Legacy options deleted rather than discouraged. AEAD only, forward secrecy compulsory, one round trip. |
How TLS 1.3 gets to one round trip, and what it deleted to do it. In TLS 1.2 the client cannot send its key share until it has seen which group the server picked, which costs a whole round trip. TLS 1.3 has the client guess: it puts a key share for the group it expects into the ClientHello itself. The server usually accepts that group, replies with its own share in the ServerHello, and at that moment both sides can derive keys. So everything the server sends after the ServerHello is already encrypted, including the certificate, which was in the clear in TLS 1.2. The client then sends its Finished and its HTTP request in the same flight, which is why the count is one round trip and not two. The deletions are the other half of the story: no RSA key transport, no static Diffie-Hellman, no CBC modes, no RC4, no compression and no renegotiation, and the suite list shrank from hundreds to five. There is also 0-RTT resumption, where a returning client sends data in its very first flight using a key remembered from an earlier session, at the cost of no forward secrecy for that early data and no protection against it being replayed.
Finally, the payoff of TLS being a layer rather than a protocol. Every one of these keeps its own commands and its own grammar and runs them unchanged inside TLS. There are two ways to arrange that, and the difference is examinable: implicit TLS starts the handshake on the very first byte on a dedicated port, while explicit TLS begins as an ordinary plaintext session on the normal port and upgrades in place with a command such as STARTTLS.
| Protocol | Plaintext port | Upgrade in place (explicit) | TLS from byte zero (implicit) |
|---|---|---|---|
| HTTP | 80 | Not used in practice. | 443 — this is all HTTPS is. |
| SMTP submission | 587 | STARTTLS on 587. | 465 |
| SMTP between servers | 25 | STARTTLS on 25, opportunistically. | — |
| IMAP | 143 | STARTTLS on 143. | 993 |
| POP3 | 110 | STLS on 110. | 995 |
| FTP | 21 control, 20 data in active mode | AUTH TLS on 21. | 990 |
| LDAP | 389 | The Start TLS extended operation on 389. | 636 |
| DNS | 53 | — | 853 for DNS over TLS; DNS over HTTPS rides on 443. |
| SSH on port 22 is deliberately not in this table. It does the same three jobs, but with its own protocol, its own key format and its own handshake, and it authenticates the server with a host key you trusted the first time you connected rather than with a CA-signed certificate. "SSH uses TLS" is a wrong answer that sounds right. | |||
Explicit upgrades have a weakness that implicit ports do not. On port 587 the first few lines of conversation are plaintext, and the server advertises STARTTLS in that plaintext. An attacker who can rewrite packets can delete that advertisement, the client concludes the server does not support TLS, and the session continues in the clear with neither side alarmed. On port 465 there is no plaintext conversation to edit. This is why the mail standards moved back towards implicit TLS, and why HSTS exists on the web: a 301 redirect from port 80 to port 443 still leaves one plaintext request that an attacker can intercept, and the Strict-Transport-Security header, plus the preload list shipped inside browsers, removes even that one.
Close on the limits, because "TLS protects everything" is the answer that gets picked apart. Here is what a passive observer captures from our connection, straight off the record layer. The first byte of every TLS record is its type, and the two after it are a version, so an observer can classify records without decrypting anything.
-- four of the TLS records of https://www.example.com/ , as captured16 03 01 00 c5 Handshake ClientHello readable: versions, random, suites, SNI=www.example.com16 03 03 00 51 Handshake ServerHello readable: chosen version and cipher suite16 03 03 0b 8e Handshake Certificate readable: the entire X.509 chain, 2958 bytes of it17 03 03 01 f4 ApplicationData opaque: the 500-byte length covers the ciphertext and its 16-byte tag -- 0x16 = handshake, 0x17 = application data, 0x14 = change cipher spec, 0x15 = alert-- the two bytes after the type are a version; the two after that are the record length-- the ClientHello record reads 03 01 to get past old middleboxes; the real version is chosen inside the hellos
What TLS still does not hide. Three things, and you should be able to say all three. First, the server’s IP address, which sits in the IP header outside everything TLS touches; TLS cannot encrypt the address a packet has to be routed to. Second, how much data flowed and when. Record lengths are visible, timing is visible, and traffic analysis on those two alone can identify which video you streamed or which page of a site you loaded. Third, and most often forgotten, the hostname. The Server Name Indication extension exists because one IP address serves many sites and the server must know which certificate to present, so the name is sent in the ClientHello before any key exists, in the clear, in TLS 1.3 as much as in TLS 1.2. TLS 1.3 encrypting the certificate closes one leak and leaves this one wide open. Encrypted Client Hello is the fix for it and is still being rolled out. On top of that, the DNS lookup that found the address was probably plaintext on port 53 unless you were using DNS over TLS on 853 or DNS over HTTPS on 443.
05 Cheat sheet
The answers that get asked, and the wrong ones that get given
Every row is something you should be able to state in under ten seconds. The right-hand column is the specific wrong answer that gets written down, not a general caution.
| What they ask | The answer | The trap |
|---|---|---|
| What does TLS give you | confidentiality, integrity, authentication | "it encrypts the data" — that is one of the three, and not the interesting one |
| Which mechanism gives each one | symmetric cipher · authentication tag · certificate | Naming the guarantees without the mechanisms. The follow-up is always "how". |
| Why both kinds of cryptography | asymmetric to authenticate and agree a key, symmetric to carry the data | "TLS encrypts your data with RSA" — it never encrypts bulk data with RSA |
| Is the session key sent | no · each side derives it from a Diffie-Hellman exchange | Saying the server sends the key encrypted. That was RSA key transport, deleted in TLS 1.3. |
| What is in a certificate | hostnames, the public key, validity dates, issuer, the CA’s signature | "the private key" — it is never in the certificate and never on the wire |
| Which message authenticates the server | the signed key exchange, not the certificate on its own | Saying "the certificate". Anyone can copy a certificate; only the key holder can sign. |
| Where the handshake goes encrypted | TLS 1.2 at the first Finished · TLS 1.3 right after the ServerHello | "the whole handshake is encrypted" — the hellos never are, in either version |
| Which version, which round trips | TLS 1.2 needs 2 · TLS 1.3 needs 1 | swapping them — 1.3 is the newer and the faster one |
| Is the certificate encrypted | cleartext in TLS 1.2 · encrypted in TLS 1.3 | Assuming it is protected in both. It is one of the biggest visible changes in 1.3. |
| Which versions are dead | SSL 2.0 and 3.0, TLS 1.0 and 1.1 · RFC 8996 | calling any of it "SSL" in an answer about a live system |
| What HTTPS is | HTTP, unchanged, inside TLS, on port 443 | Describing it as a different protocol with different methods or status codes. |
| Forward secrecy | ephemeral DH keys, destroyed at close, so a future key theft reveals nothing | "the certificate expires" — expiry has nothing to do with it |
| What TLS does not hide | the server IP, the volume and timing, and the SNI hostname | Claiming the hostname is protected in TLS 1.3. Only the certificate is. |
06 Where & why
Four systems where this is a command you type
None of this is a diagram from a textbook. Every message in section 03 is something you can print on your own machine in one command, and three of the four systems below differ from the plain description in a way worth naming out loud.
openssl s_client -connect www.example.com:443 -servername www.example.com runs a real handshake and prints the certificate chain it received, the negotiated protocol and cipher, and a line reading Verify return code: 0 (ok) when the chain validated. The -servername flag is the SNI, and leaving it off on a shared host gets you the wrong certificate, which is itself a good demonstration of what SNI is for. Add -tls1_2 or -tls1_3 to force a version and see the message order change.
ACME is a protocol for proving you control a hostname, by serving a token at a URL under it or publishing one in its DNS, after which a certificate is issued automatically. Certificates last 90 days, which forces renewal to be a cron job rather than a calendar reminder. Note precisely what the CA verified: control of the name. It did not verify that the operator is honest, which is why a padlock on a phishing site is not a contradiction.
ssl_certificate must point at a file containing the leaf certificate followed by the intermediates, in that order, because that is the sequence the server sends. ssl_certificate_key points at the private key, which is the file that never leaves the machine. ssl_protocols TLSv1.2 TLSv1.3; is how you refuse the deprecated versions, and ssl_stapling on; turns on OCSP stapling so the freshness proof rides along with the handshake.
Chrome ships its own root store rather than using the operating system’s, so the set of authorities you trust is a list somebody curates and can remove entries from. It also enforces Certificate Transparency: a public certificate must appear in public append-only logs or Chrome rejects it, which makes a quietly misissued certificate detectable. And it ships a HSTS preload list, so for the sites on it the browser goes straight to https:// and never sends the first plaintext request at all.
07 Interview questions
What they ask, and what they follow up with
This topic is asked in two ways. In a networks round it is "walk me through the handshake". In a systems or security round it is "why is that safe", and the second one is where candidates run out of material after two sentences. Answer with mechanisms rather than adjectives: "a signature over both randoms" is an answer, "it is secure" is not.
What does TLS actually give you?
Why does TLS use both symmetric and asymmetric cryptography instead of picking one?
Is the session key sent across the network?
What is inside a certificate, and what has the CA actually verified?
The data is encrypted either way. Why does authentication matter?
Walk me through the TLS 1.2 handshake, and tell me what an observer can read.
What did TLS 1.3 change, and how many round trips does each version need?
What is forward secrecy?
Is HTTPS a different protocol from HTTP?
What does TLS not protect?
An attacker deletes the four strongest cipher suites from a ClientHello in flight. Does the handshake still succeed?
08 Practice problems
Six to work on paper
Two of these are arithmetic and want a pen. Two are certificate failures, so write out the four checks a client makes before it trusts a server and find the one that fails, because in both of those exactly one thing is wrong and the other three are fine. The last two are about where in a session TLS starts, and what a connection gives up to start it early.