SP 800-227 — KEM Usage Guidance
NIST Special Publication 800-227, "Recommendations for Key-Encapsulation Mechanisms" (final, Sept 2025), is guidance — not a new algorithm. It tells implementers how to use KEMs such as ML-KEM correctly: key derivation, combiners, and the pitfalls to avoid.
Why a usage document is needed
FIPS 203 specifies what ML-KEM computes; it does not fully specify how to wire a KEM into a real protocol. Most cryptographic failures in practice come not from broken algorithms but from misuse — feeding a shared secret directly into a cipher, mishandling decapsulation failures, or combining secrets insecurely. SP 800-227 closes that gap with normative guidance for the KEM ecosystem.
The KEM interface
A KEM exposes three operations:
| Operation | Input | Output |
|---|---|---|
KeyGen | — | (public key, private key) |
Encaps | public key | (ciphertext, shared secret) |
Decaps | private key, ciphertext | shared secret |
Correct KEM use: the rules
- Always run the shared secret through a KDF. The raw KEM shared secret (32 bytes for ML-KEM) is not a finished key. Derive your actual keys with an approved KDF (e.g., HKDF, KMAC) that also binds in context: the protocol identifier, the public key/ciphertext, and a transcript hash.
- Bind the public values into key derivation. Include the encapsulation key and ciphertext in the KDF input so the derived key is tied to this exact exchange (helps prevent reflection and key-reuse attacks).
- Respect implicit rejection. ML-KEM never signals decapsulation failure; on a bad ciphertext it returns a pseudorandom secret. Do not add your own failure branch that leaks whether decapsulation "succeeded" — that reintroduces a timing/oracle vulnerability the FO transform was designed to remove.
- Treat shared secrets as ephemeral. Do not log, cache, or reuse them; derive session keys and discard.
Combiners and hybrids
During the transition, most deployments run a hybrid: a classical KEM/DH (e.g., X25519) alongside ML-KEM. A KEM combiner merges the two shared secrets into one so that the result is secure if either component remains unbroken. SP 800-227 gives guidance on doing this safely:
- Feed both shared secrets plus both ciphertexts/public keys into a single KDF call — do not XOR raw secrets naively.
- Use a combiner with a security proof (e.g., concatenation-then-KDF with proper labeling).
- Ensure the combiner is robust: a malicious or malformed component must not undermine the honest one.
# Teaching example: hybrid KEM combiner (bind context, then KDF)
import hashlib, hmac
def hkdf_extract(salt, ikm):
return hmac.new(salt, ikm, hashlib.sha256).digest()
def hkdf_expand(prk, info, length=32):
okm = b""
t = b""
counter = 1
while len(okm) < length:
t = hmac.new(prk, t + info + bytes([counter]), hashlib.sha256).digest()
okm += t
counter += 1
return okm[:length]
def combine(ss_classical, ss_pqc, ct_classical, ct_pqc, context):
ikm = ss_classical + ss_pqc
salt = hashlib.sha256(ct_classical + ct_pqc + context).digest()
prk = hkdf_extract(salt, ikm)
return hkdf_expand(prk, b"hybrid-kem-v1 session-key", 32)
Standards & references
- SP 800-227 — Recommendations for Key-Encapsulation Mechanisms (final, Sept 2025; Initial Public Draft was Jan 2025)
- FIPS 203 — ML-KEM (final, 13 Aug 2024)
- NIST Post-Quantum Cryptography project
SP 800-227 KEM 使用指引
NIST 特别出版物 800-227《密钥封装机制建议》(2025 年 9 月正式发布)是一份使用指引,而非新算法。它告诉实现者如何正确使用 ML-KEM 等 KEM,涵盖密钥派生、组合器以及应当规避的各类陷阱。
为何需要一份使用文档
FIPS 203 规定了 ML-KEM 算什么,却没有完整规定如何把 KEM 接入真实协议。实践中,多数密码故障并非源于算法被攻破,而是源于误用:把共享密钥直接喂给密码算法、错误处理解封装失败,或以不安全的方式组合密钥。SP 800-227 正是以面向 KEM 生态的规范性指引填补了这一空缺。
KEM 接口
KEM 暴露三项操作
| 操作 | 输入 | 输出 |
|---|---|---|
KeyGen | — | 公钥私钥 |
Encaps | 公钥 | 密文共享密钥 |
Decaps | 私钥密文 | 共享密钥 |
正确使用 KEM 的规则
- 始终让共享密钥经过 KDF。原始 KEM 共享密钥(ML-KEM 为 32 字节)并非成品密钥。请用经批准的 KDF(如 HKDF、KMAC)派生实际密钥,并绑定上下文——协议标识符、公钥/密文以及握手记录哈希。
- 把公开值绑入密钥派生。将封装密钥与密文一并纳入 KDF 输入,使派生密钥与本次交换严格绑定,有助于防范反射攻击与密钥重用攻击。
- 尊重隐式拒绝。ML-KEM 从不报告解封装失败,遇到坏密文时返回一个伪随机密钥。切勿自行添加泄露解封装成败的失败分支,那会重新引入 FO 变换本欲消除的时序或预言机漏洞。
- 把共享密钥视为临时值。不要记录、缓存或重用;派生出会话密钥后即应丢弃。
组合器与混合
过渡期内,多数部署采用混合模式,即让经典 KEM/DH(如 X25519)与 ML-KEM 并行。KEM 组合器把两个共享密钥合并为一个,使得只要任一组件未被攻破,结果就仍然安全。SP 800-227 给出了安全做法的指引:
- 将两个共享密钥连同两份密文/公钥一并喂入单次 KDF 调用,切勿朴素地把原始密钥异或了事。
- 使用带安全证明的组合器,例如“先连接后 KDF”,并正确加标签。
- 确保组合器具备稳健性:恶意或畸形的组件不得削弱诚实组件的安全。
# 教学示例 混合 KEM 组合器 先绑定上下文 再 KDF
import hashlib, hmac
def hkdf_extract(salt, ikm):
return hmac.new(salt, ikm, hashlib.sha256).digest()
def hkdf_expand(prk, info, length=32):
okm = b""
t = b""
counter = 1
while len(okm) < length:
t = hmac.new(prk, t + info + bytes([counter]), hashlib.sha256).digest()
okm += t
counter += 1
return okm[:length]
def combine(ss_classical, ss_pqc, ct_classical, ct_pqc, context):
ikm = ss_classical + ss_pqc
salt = hashlib.sha256(ct_classical + ct_pqc + context).digest()
prk = hkdf_extract(salt, ikm)
return hkdf_expand(prk, b"hybrid-kem-v1 session-key", 32)
标准与参考
- SP 800-227 密钥封装机制建议 2025 年 9 月正式发布,首个公开草案为 2025 年 1 月
- FIPS 203 ML-KEM 正式 2024 年 8 月 13 日
- NIST 后量子密码项目