Skip to main content

All weeks · Worksheet · Overview

Week 13 · Lecture slides

Week 13

Contents17 sections

End-to-End Encryption (TLS is not enough; the server still reads your messages)

Security & Cryptography · Nutthakorn Chalaemwongwan


Today

  • Transport encryption (TLS/HTTPS) vs. end-to-end encryption (E2EE) — different guarantees
  • The server as a trusted third party: TLS terminates there
  • Hybrid encryption at the endpoints: AES-256-GCM wrapped in RSA-OAEP
  • What E2EE still doesn't prove: the root-of-trust problem
  • 👀 Game: Who's Reading Your Mail?

Recap — Week 12

  • TLS asked: is this channel going to the right endpoint? (certificate-validation MITM)
  • The fix was checking the chain to a trusted CA before sending anything
  • This week: even when the channel IS the right endpoint, that endpoint is the server — and encryption to the server is not encryption from the server

Two different guarantees

Transport encryption (TLS/HTTPS)End-to-end encryption (E2EE)
Protects datain transitfrom the server operator itself
Hides plaintext froma network eavesdropperthe provider running the service
Where plaintext can existat every hop, incl. the serveronly on the two endpoints

The first does not imply the second. That confusion is the whole lesson.


Why: the server terminates TLS

Alice → [TLS] → Server → [TLS] → Bob

  • The server decrypts, holds plaintext, then re-encrypts to forward it
  • It is a trusted third party by construction, not by accident — app logic, routing, storage all need plaintext at that hop
  • A TLS-only provider can read, log, subpoena-respond-to, scan, or leak every message that passes through

The break: a threat-model mismatch, not a broken primitive

  • CWE-311 — Missing Encryption of Sensitive Data
  • CWE-319 — Cleartext Transmission of Sensitive Information (here: cleartext storage on the relay, even though transit was encrypted)
  • TLS is not defeated — it's answering a question nobody asked: "is the wire safe?" not "is the operator safe?"

Textbook-secure primitive: TLS does exactly what it promises. Real-system failure: assuming that promise covers something it never claimed.


The fix: move the boundary to the endpoints

  • A fresh AES-256-GCM key is generated per message (fast, symmetric)
  • That key is wrapped to the recipient's public key with RSA-OAEP (NIST SP 800-56B) — hybrid encryption
  • Encryption happens on the sender's device; decryption happens on the recipient's device — the server never holds a key that opens either
  • Same hybrid pattern as Week 10's KEM/DEM — deployed here into an actual messaging shape

The demo: one server, two client roles

ServiceRoleWhat it does
server.pyThe provider/pubkey, /send, /fetch. Logs verbatim: SERVER SAW: <payload>. Byte-for-byte identical code in both modes — it has no idea whether E2EE is on.
alice.pySenderVulnerable: sends raw plaintext. Fixed: fetches bob's public key, encrypts client-side before sending.
bob.pyRecipientVulnerable: reads plaintext. Fixed: generates an RSA keypair in memory, publishes only the public half, decrypts client-side → BOB DECRYPTED: <secret>.

Vulnerable mode — watch your own log leak

week13-server  | SERVER: listening on 0.0.0.0:8080 (E2E=False)
week13-alice   | ALICE: sending the raw plaintext (no E2EE)
week13-server  | SERVER SAW: meet at pier 39 at midnight
week13-bob     | BOB RECEIVED: meet at pier 39 at midnight

The SERVER SAW: ... line is your personalized evidence artifact for this HYBRID week — pair it with your identity proof.


Fixed mode — same server, unreadable log

week13-server  | SERVER: listening on 0.0.0.0:8080 (E2E=True)
week13-bob     | BOB: published my public key, waiting for a message
week13-alice   | ALICE: encrypted the secret to bob's public key (client-side)
week13-server  | SERVER SAW: eyJlbmNfa2V5IjogImdQY29aZVcrSUdOSVJt...
week13-bob     | BOB DECRYPTED: meet at pier 39 at midnight

grep -c "meet at pier 39 at midnight" on the server log → 0 (vs. 1 in vulnerable mode).


What this lab does NOT prove — root of trust

  • Alice trusts whatever public key the server hands her
  • A malicious server could substitute its own key — a public-key MITM, the messaging cousin of Week 5's Diffie–Hellman MITM
  • This lab proves the server cannot read an E2EE message — it does not prove Alice is talking to the real Bob
  • Stays conceptual this week: Worksheet Q2 and the Audit-the-AI exercise

Why encrypted email (PGP) never took off

  • Key discovery: how do you even get someone's public key in the first place?
  • Metadata leaks even when the message body is encrypted (who, when, subject lines in S/MIME)
  • Usability: "manage your own long-term keyring" defeated ordinary users — Whitten & Tygar, Why Johnny Can't Encrypt, USENIX Security 1999

How Signal improves on PGP

  • TOFU (trust on first use) — key management happens automatically, mostly invisible to the user
  • X3DH — an asynchronous handshake; works even if Bob is offline when Alice sends
  • Double Ratchet — forward secrecy (a key compromise today doesn't expose past messages) + post-compromise security (the session heals after a compromise)

👀 Game — Who's Reading Your Mail?

  • Play the messaging provider: tail your own server's log while a "private" message passes through
  • Watch it sit there in plaintext, sender's name and all
  • Flip the client to encrypt client-side — watch your own log turn into unreadable ciphertext, while the recipient still decrypts it perfectly

Lab today — Worksheet 13

📋 Worksheet 13 — labs/week13-e2e-encryption/worksheet.md · kickoff: docker compose -f docker-compose.vulnerable.yml up --build, then the .fixed.yml file

  • Part 1 (essays): TLS vs. E2EE, the root-of-trust problem, why PGP failed, Signal vs. PGP, open problems in E2EE
  • Part 2a (lab): capture both modes' logs — plaintext SERVER SAW vs. base64 SERVER SAW, BOB DECRYPTED, and the grep -c showing 0
  • 🤖 Audit the AI: critique an AI-written "secure chat backend" that calls itself end-to-end encrypted because it uses HTTPS — same flaw as vulnerable mode, dressed up in reassuring language
  • 🧠 EiPE + Prompt Problem: explain WhatsApp's "lock icon" to a non-technical friend; probe an AI on TLS vs. E2EE and check it for hallucinated claims

Key takeaways

  • HTTPS/TLS protects the wire — it does not protect you from the operator; that's a different guarantee entirely
  • Textbook-secure primitive, real-system failure: TLS wasn't broken — it was trusted for something it never promised
  • E2EE closes the gap with hybrid encryption (AES-256-GCM + RSA-OAEP) moved to the endpoints — but it still doesn't solve whose key you're actually encrypting to (root of trust)

Questions?

Next week: (see course roadmap)

All weeks in Security & Cryptography