Key Encapsulation Mechanisms (KEMs)
A KEM is the post-quantum replacement for RSA key transport and Diffie-Hellman key agreement. It is a three-algorithm interface that lets two parties establish a fresh shared symmetric secret over an insecure channel, which then seeds the symmetric encryption that protects the actual traffic.
The three-algorithm API
Every KEM contains at least three core operations:
- KeyGen() →
(ek, dk)— produces an encapsulation keyek(public) and a decapsulation keydk(private). - Encaps(ek) →
(ct, K)— the sender, holding the recipient's publicek, generates a ciphertextctand a shared secretK. - Decaps(dk, ct) →
K— the recipient uses the privatedkto recover the same shared secretKfromct.
After a successful exchange both parties hold the identical shared secret K. For ML-KEM, FIPS 203 specifies a 32-byte shared key; the output length of other KEMs should be taken from their respective specifications. An eavesdropper who saw ek and ct learns nothing about it.
How a KEM differs from DH and RSA key transport
It is tempting to think of a KEM as "just Diffie-Hellman", but the shape is different:
- Versus Diffie-Hellman: DH is a two-sided agreement — both parties contribute a public share and combine them. A KEM is one-sided: the sender encapsulates to a recipient's public key. There is no symmetric "both contribute" step. This matters for protocol design, because a single KEM call replaces the DH share exchange.
- Versus RSA key transport: classic RSA key transport has the sender pick a secret and encrypt it under the recipient's public key. A KEM is similar in spirit, but the secret
Kis derived from the encapsulation rather than chosen and encrypted, which avoids whole classes of padding and malleability pitfalls.
signatures.html.Security goal: IND-CCA2
Standardized KEMs such as ML-KEM target IND-CCA2 (indistinguishability under adaptive chosen-ciphertext attack). Informally: even an adversary who can submit arbitrary ciphertexts to a decapsulation oracle and observe the results cannot distinguish the real shared secret from random. This is the strong notion you want, because in practice attackers can send malformed ciphertexts and watch how a server reacts. The Fujisaki-Okamoto transform used inside ML-KEM is what lifts an IND-CPA scheme up to IND-CCA2.
You always run a KDF afterwards
The raw shared secret K should not be used directly as an encryption key. It must be passed through a key derivation function, binding in transcript or context information, to produce the actual AEAD keys. ML-KEM already applies internal hashing, but protocols layer their own KDF on top so the session keys are bound to the handshake context.
# Illustrative ML-KEM flow (pseudocode using a liboqs-style API)
from kemlib import KEM
kem = KEM("ML-KEM-768")
# Recipient generates a long- or short-term keypair
ek, dk = kem.keygen() # ek is published
# Sender encapsulates to the recipient's public key
ct, K_send = kem.encaps(ek) # ct goes on the wire
# Recipient decapsulates to recover the same secret
K_recv = kem.decaps(dk, ct)
assert K_send == K_recv
# NEVER use K directly — derive real keys via a KDF
import hashlib
session_key = hashlib.shake_256(K_recv + b"handshake-transcript").digest(32)
Which KEMs exist
The NIST-standardized and candidate KEMs are all post-quantum and all share the three-algorithm interface, but differ sharply in size and maturity:
| KEM | Family | Notes |
|---|---|---|
| ML-KEM | Lattice (module-LWE) | FIPS 203; the general-purpose default |
| HQC | Code-based | Selected as a backup with different math from ML-KEM |
| Classic McEliece | Code-based | Tiny ciphertext but very large public key (255 KB+) |
| BIKE | Code-based | Round-4 candidate, smaller keys than McEliece |
For almost all general use, ML-KEM-768 at Level 3 is the recommended starting point — it is fast, has modest sizes, and is the most widely interoperable.
ct can leak the private key through timing or reaction attacks.Related
Standards & references
- FIPS 203 (ML-KEM) — the standardized lattice key encapsulation mechanism.
- SP 800-227 — recommendations for key establishment using KEMs.
- RFC 9794 — terminology for PQ/T hybrid key establishment.
- Open Quantum Safe — liboqs and open-source PQC KEM implementations.
- Resources — full standards register
密钥封装机制 KEM
KEM 是 RSA 密钥传输与 Diffie-Hellman 密钥协商的后量子替代方案。它由三个算法构成一套接口,让通信双方在不安全的信道上协商出一个全新的共享对称密钥,再由该密钥派生出真正保护流量的对称加密密钥。
三算法接口
每个 KEM 至少包含三个核心操作。
- KeyGen() →
(ek, dk)— 生成封装密钥ek(公开)和解封装密钥dk(私有)。 - Encaps(ek) →
(ct, K)— 发送方持有接收方的公钥ek,生成密文ct和共享密钥K。 - Decaps(dk, ct) →
K— 接收方用私钥dk从ct中恢复出相同的共享密钥K。
交换成功后双方持有完全相同的共享秘密 K。对 ML-KEM,FIPS 203 规定共享密钥为 32 字节;其他 KEM 的输出长度应以对应规范为准。仅看到 ek 和 ct 的窃听者对其一无所知。
KEM 与 DH RSA 密钥传输的区别
把 KEM 简单理解为“就是 Diffie-Hellman”很有诱惑力,但二者形态并不相同:
- 相比 Diffie-Hellman:DH 是双边协商,双方各贡献一个公开份额并加以合成。KEM 是单边的:发送方朝着接收方的公钥做封装,不存在“双方共同贡献”的对称步骤。这对协议设计有影响,因为单次 KEM 调用即可取代 DH 的份额交换。
- 相比 RSA 密钥传输:经典 RSA 密钥传输是发送方挑选一个秘密、用接收方公钥加密后传出。KEM 在思路上相近,但秘密
K是从封装中派生出来的,而非自行选定再加密,从而规避了整类填充与可塑性陷阱。
signatures.html。安全目标 IND-CCA2
ML-KEM 等标准化 KEM 以 IND-CCA2(自适应选择密文攻击下的不可区分性)为目标。通俗地说:即便攻击者能向解封装预言机提交任意密文并观察结果,也无法把真实共享密钥与随机值区分开。这正是实践中所需的强安全概念,因为现实里攻击者确实能发送畸形密文并观察服务器反应。ML-KEM 内部采用的 Fujisaki-Okamoto 变换,正是将 IND-CPA 方案提升到 IND-CCA2 的关键。
事后务必再跑一次 KDF
原始共享密钥 K 不应直接用作加密密钥,必须经过密钥派生函数处理,并绑定握手记录或上下文信息,才能得到真正的 AEAD 密钥。ML-KEM 内部已做哈希处理,但协议仍会在其上叠加自己的 KDF,使会话密钥绑定到握手上下文。
# ML-KEM 流程示意(采用 liboqs 风格接口的伪代码)
from kemlib import KEM
kem = KEM("ML-KEM-768")
# 接收方生成长期或短期密钥对
ek, dk = kem.keygen() # ek 对外公开
# 发送方朝接收方公钥做封装
ct, K_send = kem.encaps(ek) # ct 在信道上传输
# 接收方解封装以恢复同一秘密
K_recv = kem.decaps(dk, ct)
assert K_send == K_recv
# 切勿直接使用 K,应经 KDF 派生真正的密钥
import hashlib
session_key = hashlib.shake_256(K_recv + b"handshake-transcript").digest(32)
现有的 KEM
NIST 标准化及候选的 KEM 全部为后量子算法,且都遵循三算法接口,但在体积与成熟度上差异显著:
| KEM | 家族 | 说明 |
|---|---|---|
| ML-KEM | 格 module-LWE | FIPS 203,通用默认选择 |
| HQC | 基于编码 | 作为备选入选,数学基础与 ML-KEM 不同 |
| Classic McEliece | 基于编码 | 密文极小但公钥极大(255 KB 以上) |
| BIKE | 基于编码 | 第四轮候选,密钥比 McEliece 小 |
对绝大多数通用场景,推荐从 Level 3 的 ML-KEM-768 起步——它速度快、体积适中,且互操作性最好。
ct 时发生分支或返回显式错误,就可能通过时序或反应攻击泄露私钥。相关链接
标准与参考
- FIPS 203 ML-KEM — 标准化的格密钥封装机制。
- SP 800-227 — 使用 KEM 进行密钥建立的建议。
- RFC 9794 — PQ/T 混合密钥建立的术语规范。
- Open Quantum Safe — liboqs 与开源 PQC KEM 实现。
- 资源链接 — 完整标准登记册