Section 7: Applied Cryptography

You now hold a full toolbox: block ciphers and AEAD modes (Section 4), hash functions, MACs, and KDFs (Section 5), and public-key encryption, signatures, and Diffie-Hellman (Section 6). Individually, each primitive solves one narrow problem. None of them, alone, is a security system. This section is about the step that actually matters in practice: composition — wiring the primitives together into protocols that survive contact with real networks, real adversaries, and real users.

Think of primitives as Lego bricks and protocols as the buildings. The bricks — AES-GCM, SHA-256, X25519, Ed25519 — are astonishingly solid; direct mathematical breaks of modern primitives are vanishingly rare. Real-world cryptographic failures almost always live in the mortar: a protocol that authenticates the wrong thing, a key reused where it must be fresh, a downgrade path an attacker can force, a signature that covers less than everyone assumed. As you read the systems below — TLS, PGP, Signal, blockchains — keep asking the composition questions: which primitive provides which guarantee, what keys exist, who holds them, and what happens when one leaks?

TLS: the protocol that carries the web

TLS (Transport Layer Security) is the S in HTTPS. Every padlock in your browser, every API call your phone makes, most email hops, and a large share of VPN traffic ride on it. TLS gives a client and server three guarantees over a hostile network: confidentiality (eavesdroppers see noise), integrity (tampered records are rejected), and authentication (you are talking to the server named in the certificate — usually one-way; the client typically authenticates later with a password or token inside the tunnel).

A quick genealogy, because the names still cause confusion:

VersionYearStatus
SSL 2.0 / 3.01995 / 1996Dead. Broken by design flaws (SSL 3.0 fell to the POODLE attack). Never use.
TLS 1.0 / 1.11999 / 2006Formally deprecated (RFC 8996, 2021). Disabled in all major browsers.
TLS 1.22008Legacy but still common; secure only with a carefully chosen cipher suite.
TLS 1.32018 (RFC 8446)Current. Simpler, faster, and with the historical foot-guns removed.

The TLS 1.3 handshake, step by step

The handshake is a negotiation that must accomplish four things before a single byte of application data flows: agree on algorithms, establish shared secret keys, prove the server’s identity, and confirm nothing was tampered with along the way. TLS 1.3 does all of it in a single round trip:

CLIENT                                                    SERVER
  |                                                          |
  |  ClientHello ------------------------------------------> |
  |    - supported TLS versions                              |
  |    - supported cipher suites (e.g. TLS_AES_128_GCM_...)  |
  |    - key_share: ephemeral ECDHE public key (e.g. x25519) |
  |    - server name (SNI), extensions                       |
  |                                                          |
  |         The client speculates: it sends its half of the  |
  |         Diffie-Hellman exchange BEFORE knowing what the  |
  |         server will pick. This is what buys 1-RTT.       |
  |                                                          |
  | <------------------------------------------ ServerHello |
  |    - chosen version + cipher suite                       |
  |    - key_share: server ephemeral ECDHE public key        |
  |                                                          |
  |   * Both sides now compute the ECDHE shared secret and   |
  |   * derive handshake keys with HKDF. EVERYTHING BELOW    |
  |   * THIS LINE IS ALREADY ENCRYPTED.                      |
  |                                                          |
  | <------------------------------------ {EncryptedExtensions}
  |    - further parameters (ALPN, etc.)                     |
  | <-------------------------------------------- {Certificate}
  |    - server certificate chain (X.509, see Section 6)     |
  | <-------------------------------------- {CertificateVerify}
  |    - signature over the handshake transcript, made with  |
  |      the private key matching the certificate            |
  | <------------------------------------------------ {Finished}
  |    - HMAC over the entire transcript: "here is what I    |
  |      think we said" -- detects any tampering             |
  |                                                          |
  |  {Finished} -------------------------------------------> |
  |    - client confirms the same transcript                 |
  |                                                          |
  |  {Application data} <==================================> |
  |    - HTTP requests/responses under AES-GCM or            |
  |      ChaCha20-Poly1305, keys derived via HKDF            |
  |                                                          |
        { } = encrypted        one round trip to first byte
The TLS 1.3 full handshake. Compare: TLS 1.2 needed two round trips before application data.

Annotate what each message achieves, and you can see every earlier section of this course click into place:

Reading a cipher suite

TLS 1.3 shrank cipher suite names dramatically because key exchange and authentication are negotiated separately now. Dissect the most common one:

        TLS _ AES_128_GCM _ SHA256
         |        |            |
         |        |            +-- hash for HKDF key derivation
         |        |                and transcript hashing
         |        +-- record AEAD: AES, 128-bit key, GCM mode
         +-- protocol family

  (a TLS 1.2 suite, for contrast, packed everything in:
   TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        ^kex  ^auth      ^cipher     ^PRF )

What TLS 1.3 fixed

0-RTT data can be replayed
Early data in a 0-RTT resumption is not protected against replay: an attacker can capture the encrypted first flight and resend it, and the server may process it twice. The attacker cannot read or modify it — only replay it verbatim. That is harmless for an idempotent GET /index.html and catastrophic for POST /transfer?amount=5000. RFC 8446 therefore requires applications to restrict 0-RTT to requests that are safe to execute more than once, and careful servers reject early data on anything state-changing.
Watch a real handshake
This is not abstract — you can inspect every message described above, right now. In your browser, open DevTools → Security tab (or click the padlock) to see the negotiated protocol version, cipher suite, and certificate chain of this very page’s host. From a terminal, curl -v https://example.com prints the TLS version and suite, and openssl s_client -connect example.com:443 -tls1_3 dumps the full certificate chain and handshake details. Pair either with the annotated byte-by-byte walkthrough at tls13.xargs.org (linked in Resources) and the diagram above becomes real packets.

PGP/GPG: encrypted email and the web of trust

Pretty Good Privacy (1991) and its open implementation GnuPG (GPG) apply the same primitives to a very different setting: store-and-forward email, where there is no interactive handshake — you must encrypt a message today that the recipient decrypts whenever they get around to it.

PGP is the classic example of hybrid encryption, and the pattern is worth internalizing because nearly every system that "encrypts with RSA" actually does this:

  1. Generate a random one-time session key (e.g. 256 bits for AES).
  2. Encrypt the message body with a symmetric cipher under that session key — fast, and works for any size.
  3. Encrypt the small session key with each recipient’s public key (RSA or ECC). Three recipients means three encrypted copies of the same session key, one message body.
  4. Optionally, sign: hash the message and sign the digest with the sender’s private key, so recipients get authenticity and integrity too.
             random                message
           session key K          plaintext
                |                     |
     +----------+----------+          |
     |          |          |          v
  RSA-enc    RSA-enc    RSA-enc    AES-enc(K)
 (Alice pk) (Bob pk)  (Carol pk)      |
     |          |          |          |
     +----------+----------+----------+----> one PGP message,
                                             decryptable by any
                                             of the three recipients
Hybrid encryption: asymmetric crypto moves the key, symmetric crypto moves the data.

Where TLS delegates trust to certificate authorities, PGP proposed the web of trust: users sign each other’s keys, and you accept a stranger’s key if enough people you already trust have vouched for it. Decentralized and CA-free in theory; in practice the web never grew dense enough, key-signing parties stayed a niche ritual, and most users ended up trusting keys on first use with no verification at all.

Honesty requires saying why PGP largely lost, despite three decades of effort:

GPG remains genuinely useful for signing software releases and Git tags, and for file encryption. The commands you will actually use:

# generate a key pair (interactive prompts)
gpg --full-generate-key

# encrypt a file for a recipient (by email or key ID)
gpg --encrypt --recipient alice@example.org secret.txt

# decrypt (uses your private key automatically)
gpg --decrypt secret.txt.gpg > secret.txt

# make a detached signature over a file
gpg --detach-sign release.tar.gz

# verify a signature
gpg --verify release.tar.gz.sig release.tar.gz

# sign AND encrypt in one step
gpg --sign --encrypt --recipient alice@example.org secret.txt
Modern alternative: age
For encrypting files (as opposed to email), the modern tool age deliberately does less than GPG: no key servers, no web of trust, no configuration — just short X25519 keys and ChaCha20-Poly1305, with no way to hold it wrong. age -r <recipient-key> -o secret.age secret.txt and you are done. For messaging, the answer is not better PGP; it is the protocol in the next section.

End-to-end encryption: the Signal protocol

End-to-end encryption (E2EE) means keys exist only on the endpoints: the server that relays your messages stores and forwards ciphertext it mathematically cannot read. TLS alone does not give you this — TLS protects the hop from your phone to the server, but the server sees plaintext. E2EE encrypts through the server. The state of the art is the Signal protocol, designed by Moxie Marlinspike and Trevor Perrin, and it solves two problems PGP never did: starting an encrypted session with someone who is offline, and limiting the damage when keys eventually leak.

X3DH: agreeing on a key with someone who is asleep

Diffie-Hellman needs both parties present; your contact is on a plane. X3DH (Extended Triple Diffie-Hellman) fixes this with prekeys. When Bob installs the app, his device uploads to the server:

When Alice wants to message the sleeping Bob, she fetches this "prekey bundle" and performs several DH computations — her identity and ephemeral keys crossed against Bob’s identity, signed prekey, and one one-time prekey — and hashes the results together into a shared secret. Mixing the identity keys authenticates both parties; mixing the ephemeral and one-time keys makes the secret fresh. Her first message carries the public values Bob needs to run the same computation when he wakes up. Asynchronous, mutually authenticated key agreement — no handshake required.

The Double Ratchet: keys that heal

The X3DH secret only seeds the session. From there, every single message is encrypted under a different key, produced by the Double Ratchet — two interlocking mechanisms, both named for their one-way motion:

 X3DH secret
     |
     v                DH ratchet (turns of conversation)
  root key --new DH--> root key' --new DH--> root key'' ...
     |                    |                     |
     v                    v                     v
  chain key            chain key'            chain key''
     |  \                 |  \                  |  \
    KDF  msg key 1       KDF  msg key 1        KDF  msg key 1
     |  \                 |  \                  ...
    KDF  msg key 2       KDF  msg key 2
     |                    |
     v                    v          each arrow is one-way:
    ...                  ...         old keys are unrecoverable
The Double Ratchet: symmetric ratchets step per message (forward secrecy); the DH ratchet steps per reply (post-compromise security).

Plainly: forward secrecy means a compromise today cannot decrypt the past; post-compromise security means the future re-secures itself once the attacker loses access. PGP offers neither. Signal offers both, automatically, for billions of users — the protocol runs inside Signal itself, WhatsApp, Google Messages (RCS), and Facebook Messenger.

One thing no protocol can automate is knowing you have the right public key rather than an impostor’s — the server hands out prekey bundles, and a malicious server could hand out its own. Signal surfaces this as safety numbers: a short fingerprint of both parties’ identity keys, displayed as digits and a QR code. Compare them over another channel (in person, on a call) and a machine-in-the-middle becomes detectable; the app also warns loudly whenever a contact’s identity key changes.

Blockchain: cryptography as ledger glue

Bitcoin is a composition exercise using almost nothing but Sections 5 and 6: hashes, Merkle trees, and signatures, arranged so that thousands of mutually distrusting strangers can agree on a ledger. There is no encryption anywhere in the core protocol — a point worth dwelling on below.

Hash chains make history tamper-evident. Every block header contains the SHA-256 hash of the previous block’s header. Alter any transaction in an old block and its hash changes; the next block’s stored "previous hash" no longer matches, so that block’s hash changes too, and the mismatch cascades to the tip of the chain. You cannot quietly edit history — you can only fork it, visibly, and then lose the race to re-mine everything after your edit.

 +-------------------+     +-------------------+     +-------------------+
 | BLOCK N           |     | BLOCK N+1         |     | BLOCK N+2         |
 |  prev: hash(N-1)  |<----|  prev: hash(N)    |<----|  prev: hash(N+1)  |
 |  merkle root      |     |  merkle root      |     |  merkle root      |
 |  nonce, time, ... |     |  nonce, time, ... |     |  nonce, time, ... |
 +-------------------+     +-------------------+     +-------------------+

  change one tx in block N  =>  hash(N) changes  =>  N+1's "prev" is
  wrong  =>  every later block must be re-mined: tamper-evidence
Each header commits to its predecessor; the chain is one long chain of hash commitments.

Merkle trees compress a block’s transactions into one hash. Transactions are paired and hashed, the results paired and hashed again, up to a single Merkle root stored in the header. A lightweight wallet can verify that its transaction is inside a block by checking only log₂(n) sibling hashes — for 4096 transactions, just 12 hashes — instead of downloading them all.

Merkle root H(H1 || H2) H(H3 || H4) H1=H(tx1) H2=H(tx2) H3=H(tx3) H4=H(tx4) tx1 tx2 tx3 tx4
A Merkle tree: proving tx3 is in the block needs only H4 and H(H1||H2).

Signatures define ownership. A Bitcoin "account" is just an ECDSA key pair on the secp256k1 curve (Section 6). Coins are locked to a public key; spending them means publishing a transaction signed by the matching private key, which every node verifies. Your address is not the public key itself but a hash of it (SHA-256 then RIPEMD-160, plus encoding) — shorter, and the raw public key stays hidden until you first spend. Lose the private key and the coins are frozen forever; there is no CA, no recovery, no one to call.

Proof-of-work is a partial preimage search. To append a block, a miner must find a nonce such that SHA-256 of the block header falls below a target — in practice, a digest starting with many zeros. Because a good hash function gives no shortcut (Section 5), the only strategy is brute force: guess, hash, repeat, quintillions of times per second network-wide. Each extra leading zero bit doubles the expected work; each leading zero hex digit multiplies it by 16. That asymmetry is the whole trick: finding a valid nonce is expensive, verifying one is a single hash — so rewriting history costs more than the network of honest miners spends extending it.

Blockchain is not encryption
A persistent myth says blockchains keep data "encrypted and secure". They do not. Every transaction, amount, and address on a public blockchain is permanently visible to the entire world — that radical transparency is precisely how strangers audit the ledger. The cryptography used is hashing (integrity, chaining, PoW) and signatures (authorization), not confidentiality. Bitcoin is pseudonymous at best: addresses are not names, but chain-analysis firms routinely link them to identities. Never put secrets on a chain; assume everything you broadcast is public forever.
Proof-of-work miner

Feel the difficulty curve yourself. The widget appends an incrementing nonce to your text and computes SHA-256(text + nonce) until the digest begins with the chosen number of zero hex digits. Each extra zero multiplies the expected work by 16 — watch the attempt counter.

Ready. (Real Bitcoin difficulty is currently ~19 leading zero hex digits.)

Check your understanding

Resources

toolThe Illustrated TLS 1.3 Connection
Every byte of a real TLS 1.3 handshake, annotated and explained. The single best companion to the sequence diagram on this page.
videoComputerphile — Transport Layer Security (TLS)
Approachable whiteboard walkthroughs of TLS, key exchange, and handshake concepts; see also the follow-up TLS Handshake Deep Dive episode.
articleSignal Protocol Documentation
The primary specifications for X3DH and the Double Ratchet, written by the protocol designers. Surprisingly readable.
pdfBitcoin: A Peer-to-Peer Electronic Cash System
The original nine-page Satoshi Nakamoto whitepaper: hash chains, Merkle trees, and proof-of-work composed into digital cash.
bookReal-World Cryptography — David Wong
The modern applied-crypto book: TLS, Signal, cryptocurrencies, and end-to-end encryption explained from the practitioner side.
articleCloudflare Learning Center — What is TLS?
Clear introductory articles on TLS, handshakes, and certificates from an operator that terminates a large fraction of the web’s TLS.