Most cryptographers used to assemble public-key encryption out of spare parts — pick an ECDH curve, pick an AEAD, write your own glue, hope nobody footguns it. HPKE is the standardized version of that glue. It's now load-bearing under MLS, TLS Encrypted Client Hello, and Oblivious DNS, and it's quietly the most important new crypto primitive of the last five years.
HPKE — Hybrid Public Key Encryption — is published as RFC 9180 by the IRTF Crypto Forum Research Group. The name is plain-spoken: it does public-key encryption, hybrid in the sense that it combines an asymmetric Key Encapsulation Mechanism (KEM) with a symmetric Authenticated Encryption with Associated Data (AEAD) construction. The combination isn't new. The standardization is.
Before HPKE, every protocol that needed to encrypt to a public key (without a full TLS handshake) reinvented the same pattern: generate an ephemeral keypair, do a Diffie-Hellman exchange against the recipient's static key, derive a symmetric key, and encrypt the payload with AES-GCM or ChaCha20-Poly1305. The reinventions varied in subtle and broken ways. HPKE fixes the categories of bugs by drawing the lines once.
What HPKE Actually Does
Conceptually, HPKE provides a sealed-envelope API. The sender has the recipient's public key. The sender calls Seal, gets back an encrypted message plus an encapsulated key. The recipient — who holds the private key — calls Open on the same inputs and recovers the plaintext.
Under the hood, four building blocks compose:
- KEM — Key Encapsulation Mechanism. Produces a shared secret and an encapsulation. Concrete choice: DHKEM over X25519, P-256, P-384, P-521, or X448. Post-quantum hybrids are being layered in.
- KDF — Key Derivation Function. Turns the shared secret plus context strings into the symmetric keys actually used. HKDF-SHA256, HKDF-SHA384, HKDF-SHA512.
- AEAD — symmetric encryption with integrity. AES-128-GCM, AES-256-GCM, or ChaCha20-Poly1305.
- Mode — base, PSK, auth, or auth-PSK. Determines whether sender authentication or a pre-shared key is mixed in.
A given HPKE "ciphersuite" is just the choice of KEM, KDF, and AEAD — a tuple registered with IANA. Implementations advertise the suites they support, and protocols pick. This is the same pattern as TLS cipher suites but scoped much smaller.
Why hybrid is the right word. The KEM does an expensive elliptic-curve operation once, to establish a shared secret. The AEAD does cheap symmetric encryption on the payload. You pay public-key cost once, symmetric cost per byte. This is the same shape as TLS, just stripped down to its smallest useful unit.
The Four Modes
HPKE's mode parameter changes who authenticates what. Most uses pick one and stick with it.
| Mode | Sender | Properties |
|---|---|---|
| Base | Anonymous | Recipient knows nothing about who sent it; only that it was sealed to their public key. Most common mode. |
| PSK | Holds a shared symmetric key | Mixes a pre-shared key into derivation. Recipient learns the sender belonged to the PSK group. |
| Auth | Holds a static asymmetric key | Sender authenticates via their own static keypair. Recipient verifies sender identity cryptographically. |
| Auth-PSK | Both static key and PSK | Belt and suspenders. Both authentication mechanisms layered. |
Most real-world HPKE deployments use Base mode. The sender is genuinely anonymous because the protocol provides identity elsewhere — through TLS, through an MLS commit, through an OAuth token. HPKE doesn't have to do everything.
Single-Shot vs Streaming
The minimal API is single-shot: seal one message, open one message, done. Both sides derive the same key from the shared secret and pass a fixed nonce.
The streaming API exposes the AEAD context directly. The sender calls Seal repeatedly; the recipient calls Open repeatedly. A monotonically increasing sequence number generates a unique nonce per message. This is how MLS uses HPKE for welcome messages, and how ECH handles its inner ClientHello — many messages, one encapsulation.
The streaming form is where most subtle implementation bugs live. If the sequence number ever wraps, or if it ever resets without re-keying, AES-GCM nonce reuse breaks confidentiality and integrity simultaneously. RFC 9180 mandates explicit limits and re-keying behavior. Audit any custom HPKE wrapper against those limits.
Where HPKE Shows Up in 2026
MLS — Messaging Layer Security
MLS (RFC 9420) uses HPKE for its Welcome message — the bundle a new group member receives that lets them derive the current group key. MLS could have rolled its own asymmetric encryption, but using HPKE means MLS gets the underlying construction's security analysis for free.
TLS Encrypted ClientHello
ECH hides the server name a client is connecting to from passive observers. The mechanism is HPKE-Sealing the inner ClientHello to a public key the client fetches via DNS HTTPS records. ECH is the load-bearing reason HPKE got fast-tracked through the IRTF.
Oblivious DoH
Oblivious DNS-over-HTTPS — ODoH (RFC 9230) — uses HPKE to encrypt DNS queries inside an envelope only the resolver can open, then relays them through a proxy that knows the client IP but not the query. The proxy and the resolver each see only half the picture. HPKE is what makes the envelope sealing efficient enough to be deployable.
Privacy Pass and Anonymous Tokens
Privacy Pass extensions and related anonymous-token systems use HPKE for the issuance-to-redemption envelope, allowing a token to be issued by one party and redeemed by another without correlation.
Why It Replaces Ad-Hoc KEM+AEAD Glue
Before HPKE, the canonical reference for "encrypt to a public key" was often "look at how libsodium does sealed boxes" or "look at how Signal does X3DH." Both are fine in isolation. Neither is interoperable across protocols. Worse, both bake in specific algorithm choices that can't easily be swapped without redesigning the wire format.
HPKE separates the wire format (an encapsulation followed by ciphertext) from the algorithm choice (ciphersuite ID). Hybrid post-quantum ciphersuites are being added by registering new KEMs — the rest of the construction stays put. This matters as the industry transitions to post-quantum.
The KEM-DEM paradigm dates back to Cramer and Shoup in the late 1990s. HPKE is what you get when you take twenty-five years of attacks on its naive implementations and write down the version that survived.
Common Implementation Pitfalls
The spec is careful, but implementations are where things break:
- Re-using the encapsulated key. Each Seal must generate a fresh ephemeral. If you cache and reuse, you destroy forward secrecy and create deterministic ciphertexts.
- Wrong info string. The "info" parameter binds the encryption to its context (protocol name, version, purpose). If sender and recipient pass different info, Open fails — but if a system loops a malleable string into info, you can get cross-protocol attacks.
- AAD confusion. Associated Authenticated Data covers integrity but not confidentiality. Putting secrets in AAD leaks them. Putting message-binding metadata in AAD is correct.
- Nonce sequencing in streaming. Same warning as TLS 1.3: never reset the sequence counter without re-keying. The spec mandates rekeying limits per AEAD; respect them.
Picking a Library
Implementations vetted against the RFC and its test vectors:
- hpke-rs (Rust) — used in MLS implementations including OpenMLS.
- BoringSSL and OpenSSL 3.2+ — ECH and HTTP-over-QUIC use these.
- CIRCL (Go, by Cloudflare) — production-tested through ECH rollout.
- hpke-js — the JavaScript implementation reference. Suitable for browser ECH-adjacent work.
Rolling your own HPKE is the kind of choice that looks reasonable on a Monday and turns into a CVE by Friday. The construction is small enough to look tractable. The boundary conditions — nonce limits, info domain separation, ciphersuite negotiation, hybrid PQ wrapping — are where the time goes. Use the library.
The Takeaway
Shared standards beat ten clever local solutions, every time. If you're designing a protocol that needs to encrypt to a public key, the answer in 2026 is HPKE.
Originally published at havenmessenger.com
Top comments (0)