applied · level 5

Noise & HPKE

Patterns, handshake tokens, hybrid public-key encryption.

240 XP

Noise & HPKE

TLS is excellent, but it's also 400 pages of RFCs, has decades of baggage, and assumes you need PKI-signed certificates. For secure channels that don't need the web's trust hierarchy — VPNs, IoT, messaging groups, encrypted ClientHello itself — the industry has settled on two much smaller constructions: the Noise Protocol Framework and HPKE (Hybrid Public Key Encryption, RFC 9180). Between them they underpin WireGuard, MLS, Encrypted ClientHello, and most modern hand-rolled crypto protocols.

Analogy

Think about building a garden shed. You can hire an architect to design one from scratch — lots of choices, lots of ways to get the roof pitch wrong, a very long blueprint. Or you can pick a pre-engineered kit from a catalogue: the kit is labelled SHED-8x10-GABLE-CEDAR, every piece has already been load-tested by the manufacturer, and if you want something different you pick a different catalogue number rather than modifying this one. Noise and HPKE are the kit-shed approach to secure channels: each protocol name spells out exactly which parts you're getting, there's no on-site negotiation about which screws to use, and the whole thing has been structurally verified by the vendor before anyone puts a hammer to it.

Noise — a toolkit for interactive handshakes

Trevor Perrin (co-author of Signal's ratchet) designed Noise as a construction kit. You pick a pattern describing which keys are sent when and which Diffie-Hellman operations happen, plus a DH curve / cipher / hash triple, and you get a complete protocol with provable security properties.

A pattern name is two letters:

First Meaning
N initiator has no static key
K initiator's static key is already Known to the responder (out-of-band)
X initiator's static key is transmitted (eXchanged) during the handshake
I initiator's static key is Immediately sent in the first message

The second letter is the same four options, applied to the responder.

The five patterns you'll actually see

  • NN — no static keys. Ephemeral-only. No authentication; often used inside an already-authenticated outer channel.
  • NK — anonymous client, known server. Wireguard's "you have the server's pubkey baked in" model.
  • IK — initiator and responder both have static keys; responder's is known; initiator reveals its key in the first packet. This is Wireguard.
  • XK — both static keys exist; responder's known; initiator's kept hidden until after the responder has proven itself (privacy for the client).
  • XX — both static keys exchanged mid-handshake. The safe default when neither side has prior information.

Handshake tokens

Patterns describe handshakes using tokens:

e    — send/receive an ephemeral key
s    — send/receive a static key (may be encrypted if we have a key to encrypt under)
ee   — DH between the two ephemeral keys
es   — DH between initiator's ephemeral and responder's static
se   — DH between initiator's static and responder's ephemeral
ss   — DH between the two static keys

For example, XX is:

-> e
<- e, ee, s, es
-> s, se

Every e* or s* token runs a DH and mixes the result into the running key state. After the last message both sides derive matching transport keys from that state.

Why this is better than DIY

The Noise framework ships with machine-verifiable security proofs per pattern (Dowling et al.'s formal model, continued by Girol & co.). You don't have to re-prove confidentiality, forward secrecy, or KCI resistance — the pattern label tells you which properties hold. WireGuard picked IK because the paper spelled out exactly which attackers it stopped.

Naming and cipher suites

A full Noise protocol name looks like Noise_IK_25519_ChaChaPoly_SHA256. That's: pattern + DH curve + AEAD + hash. All four are plugged in; there's no agility mechanism. If you want different crypto, you pick a different name and bake it into the spec. This is a feature — TLS's 30 years of negotiation-related vulnerabilities come from its flexibility.

HPKE — a single-shot public-key-encrypt-then-seal

HPKE (RFC 9180) answers a simpler question: "how do I encrypt one piece of data to a recipient's public key?" That's it. No handshake, no interactivity, no negotiation.

(enc, shared) = KEM.Encap(recipient_pk)
key, nonce    = KDF(shared, info)
ciphertext    = AEAD.Seal(key, nonce, aad, plaintext)
send (enc, ciphertext)

The recipient does KEM.Decap(enc, recipient_sk) to recover shared, runs the same KDF, and opens the AEAD. Done.

HPKE is what Encrypted ClientHello uses: the browser encrypts the inner ClientHello to the server's HPKE public key (published in DNS), so the TLS handshake no longer leaks SNI to on-path observers. MLS (RFC 9420, the IETF's MLS group-messaging standard) uses HPKE to add new members to a key-schedule tree. Age uses an HPKE-like construction for file encryption.

When to reach for which

Need Use
Encrypt a small thing to a known public key, asynchronously HPKE
Establish an interactive secure channel with mutual authentication Noise (XX or IK)
Both parties already have identity verification, want low-bandwidth Noise (IK) — like Wireguard
Build a group messaging app MLS (sits on top of HPKE)
Encrypt a web request TLS 1.3 — it already exists, use it

Why every new protocol picks these

Both Noise and HPKE are constructive rather than negotiated. Instead of "we support these options, let's pick one at runtime", you say "this protocol is X" and users either support X or they don't. Backwards compatibility is handled by introducing a new protocol name, not by adding options to the old one. This is how you ship a cipher without accidentally shipping a Lucky13, POODLE, or FREAK alongside it.

They also don't do PKI. You supply keys by whatever out-of-band mechanism makes sense (configuration files for Wireguard, DNS for ECH, a credential system for MLS). This keeps the primitive separable from the trust machinery — and it's why TLS 1.3's signature_algorithms feels like sleeping in a suit next to it.

What the playground tests

You'll be shown a threat model / requirement ("anonymous client talks to a known server", "two strangers need to authenticate", "hide the initiator's identity until after the responder proves itself"). Pick the right Noise pattern. The answer-decoding skill is the point: once you know what the letters mean, every pattern name tells you the full security story at a glance. That's what separates modern protocol design from the '90s.