一、为什么不能直接用公钥加密大消息
公钥密码学(Public-Key Cryptography)的诞生解决了密钥分发这一千古难题:通信双方无须事先共享秘密即可安全通信。然而,当我们真正在工程中使用 RSA、ElGamal 等公钥加密算法时,一个严峻的现实问题立刻浮出水面——公钥加密方案对明文长度有着极为严格的限制,根本无法直接用于加密大消息。
以 RSA 为例,当模数 n 为 2048 位(256 字节)时,使用 OAEP 填充后,单次加密能处理的明文上限仅为 190 字节左右。如果采用更早期的 PKCS#1 v1.5 填充,上限也不过 245 字节。ElGamal 加密方案同样面临类似的约束:明文必须是群中的一个元素,其大小受限于所选群的阶。椭圆曲线上的公钥加密方案(如基于 ECIES 的变体)虽然密钥更短,但单次操作能携带的信息量同样有限。
除了消息长度限制之外,性能差距同样令人无法忽视。对称加密算法(如 AES-256-GCM)在现代处理器上借助硬件加速指令集(AES-NI)可以轻松达到每秒数 GB 的吞吐量。相比之下,2048 位 RSA 加密的速度大约比 AES 慢 1000 倍以上,4096 位 RSA 则更慢。即使是基于椭圆曲线的方案,其标量乘法运算的开销也远远超出对称密码的分组运算。如果我们试图用公钥算法直接加密一个 1 GB 的文件,那几乎是不可想象的等待。
这两个根本性限制——消息长度约束与性能瓶颈——自然而然地引导出一个优雅的解决思路:何不将公钥密码与对称密码结合起来?用公钥算法加密一个短小的对称密钥,再用这个对称密钥去加密任意长度的实际数据。这就是混合加密(Hybrid Encryption)的核心思想。事实上,从 PGP 到 TLS,从 S/MIME 到 Signal 协议,几乎所有现实世界的加密系统都采用了混合加密的架构。公钥算法处理自己擅长的事情——密钥封装与身份认证,对称算法则负责高效地加密大量数据。二者各司其职,相得益彰。
二、传统混合加密
最直观的混合加密方案可以描述为以下三个步骤:
第一步,发送方生成一个随机的对称密钥 k,通常为 128 位或 256 位。这个密钥是一次性的,仅用于当前这条消息的加密,因此常被称为会话密钥(Session Key)或数据加密密钥(Data Encryption Key, DEK)。
第二步,发送方使用接收方的公钥 pk 对会话密钥 k 进行加密,得到密文 c1 = Enc_pk(k)。这一步利用了公钥加密的核心能力——只有持有对应私钥的接收方才能恢复 k。由于会话密钥仅有 16 或 32 字节,远远小于 RSA 等公钥算法的明文上限,因此完全可以在一次公钥加密操作中完成。
第三步,发送方使用会话密钥 k 与一个对称加密算法(如 AES-GCM)来加密实际的明文数据 m,得到密文 c2 = SymEnc_k(m)。对称加密没有消息长度限制,且速度极快,因此无论明文有多长都能高效处理。
最终,发送方将 (c1, c2) 一起发送给接收方。接收方先用私钥 sk 解密 c1 得到会话密钥 k = Dec_sk(c1),再用 k 解密 c2 得到原始明文 m = SymDec_k(c2)。
从安全性角度分析,传统混合加密方案的安全性依赖于两个组件:公钥加密方案的安全性(用于保护会话密钥)和对称加密方案的安全性(用于保护实际数据)。直觉上看,如果攻击者既无法从 c1 中恢复会话密钥 k,也无法在不知道 k 的情况下从 c2 中提取明文信息,那么整个方案就是安全的。
然而,严格的安全性证明并非如此简单。早期的混合加密构造中,公钥加密部分与对称加密部分之间的安全性关系并不清晰。例如,如果公钥加密方案仅满足 IND-CPA(选择明文攻击下的不可区分性)安全性,那么整个混合方案是否也仅满足 IND-CPA?如果我们希望混合方案达到更强的 IND-CCA2(自适应选择密文攻击下的不可区分性)安全性,对两个组件分别有什么要求?这些问题促使密码学家们对混合加密进行更为精确的形式化研究,最终催生了 KEM/DEM 范式。
三、KEM/DEM 范式
2003 年,Cramer 和 Shoup 在他们的开创性论文中提出了 KEM/DEM 范式,将混合加密的思想提升到了严格的形式化框架。这一范式将混合加密方案清晰地分解为两个独立的密码学原语:密钥封装机制(Key Encapsulation Mechanism, KEM)和数据封装机制(Data Encapsulation Mechanism, DEM),并证明了二者的安全性可以独立分析、模块化组合。
KEM 是一个由三个算法组成的元组 (KeyGen, Encaps, Decaps)。KeyGen 算法生成公钥 pk 和私钥 sk。Encaps 算法以公钥 pk 为输入,输出一个封装密文 c 和一个对称密钥 k,写作 (c, k) <- Encaps(pk)。注意,与传统公钥加密不同,KEM 的 Encaps 并不加密一个”给定的”消息——它同时生成密钥与密文。这个看似微小的区别在安全性证明中带来了巨大的简化。Decaps 算法以私钥 sk 和封装密文 c 为输入,输出对称密钥 k = Decaps(sk, c),或在密文无效时输出一个特殊的拒绝符号。
DEM 则是一个对称加密方案,由 (Enc, Dec) 两个算法组成。Enc 以对称密钥 k 和明文 m 为输入,输出密文 c’。Dec 以对称密钥 k 和密文 c’ 为输入,输出明文 m 或拒绝。DEM 的安全性要求是一次性(One-Time)语义安全或更强的不可区分性——因为在混合加密的场景中,每个会话密钥仅使用一次。
KEM/DEM 范式的核心优势在于其模块化组合定理(Composition Theorem):如果 KEM 满足 IND-CCA2 安全性(即攻击者在获得解封装预言机的情况下,仍无法区分真实密钥与随机密钥),且 DEM 满足一次性 IND-CCA 安全性(即在密钥仅使用一次的场景下,攻击者无法区分加密结果与随机比特串),那么由二者组合而成的混合加密方案也满足 IND-CCA2 安全性。
这个定理的证明思路非常清晰:假设存在攻击者 A 能够攻破混合方案,我们可以构造一个归约(Reduction)来攻破 KEM 或 DEM。在归约中,挑战者使用 KEM 的挑战密文和(真实或随机的)密钥。如果密钥是真实的,归约忠实模拟了混合方案的安全游戏;如果密钥是随机的,DEM 的密文在信息论上独立于明文(因为密钥完全随机),因此 A 的优势消失。
笔者认为,KEM/DEM 范式纠正了一个长期存在的认知偏差。教科书往往这样描述公钥加密:「用接收方的公钥加密一条消息」。但在真实的工程系统中,公钥加密几乎从不被直接用于加密应用层消息——它的实际功能始终是建立共享密钥,也就是密钥封装。从 PGP 到 TLS,从 S/MIME 到 Signal,概莫能外。KEM/DEM 范式的深刻之处在于,它将这一工程现实提升为理论框架:KEM 负责密钥建立,DEM 负责数据保护,二者各有独立且精确的安全性定义。一旦接受这个视角,混合加密就不再是「因为公钥加密太慢而不得不采用的优化技巧」,而是使用公钥密码学最自然、最正确的方式。
这种模块化的好处是深远的。工程师可以独立地选择和替换 KEM 与 DEM 组件,只要各自满足所需的安全性定义,整体方案的安全性就有保障。这为密码算法的敏捷性(Cryptographic Agility)提供了坚实的理论基础,在后量子迁移的背景下尤为重要——我们只需将传统的基于 RSA 或 ECDH 的 KEM 替换为后量子 KEM(如 ML-KEM),而 DEM 部分完全不需要改动。
下面的时序图展示了 KEM/DEM 混合加密的完整流程,从发送方生成临时密钥到接收方恢复明文的每一步操作:
Sender(发送方) Receiver(接收方)
| |
| 1. 生成临时密钥对 (ek, dk) |
| 2. KEM.Encaps(pk_R) |
| -> 封装密文 c, 共享密钥 k |
| 3. DEM.Enc(k, plaintext) |
| -> 数据密文 ct |
| |
| -------- 发送 (c, ct) -----------------------------> |
| |
| 4. KEM.Decaps(sk_R, c) |
| -> 恢复共享密钥 k |
| 5. DEM.Dec(k, ct) |
| -> 恢复明文 plaintext |
| |
四、ECIES
椭圆曲线集成加密方案(Elliptic Curve Integrated Encryption Scheme, ECIES)是混合加密在椭圆曲线密码学中最经典的实例化。它被广泛标准化于 IEEE 1363a、SECG SEC 1、ISO/IEC 18033-2 等规范中,并在以太坊、Apple iMessage 等系统中得到实际应用。
ECIES 的完整工作流程如下:
设接收方已拥有椭圆曲线密钥对:私钥 d_R(一个大整数)和公钥 Q_R = d_R * G(椭圆曲线上的一个点,G 为基点)。
加密过程分为以下步骤。发送方生成一个临时(Ephemeral)密钥对:随机选择整数 r,计算临时公钥 R = r * G。然后发送方利用接收方的公钥计算共享秘密点 S = r * Q_R = r * d_R * G。这本质上是一次椭圆曲线 Diffie-Hellman(ECDH)密钥交换。接下来,发送方将共享秘密点 S 的坐标(通常取 x 坐标)输入密钥派生函数(Key Derivation Function, KDF),如 HKDF,导出对称加密密钥 k_enc 和 MAC 密钥 k_mac:(k_enc, k_mac) = KDF(S_x)。然后使用 k_enc 和对称加密算法(如 AES-CBC 或 AES-CTR)加密明文 m 得到密文 c,并使用 k_mac 对密文 c 计算消息认证码 t = MAC(k_mac, c)。在现代实现中,通常直接使用 AEAD 算法(如 AES-256-GCM 或 ChaCha20-Poly1305),一步完成加密与认证,此时无须单独的 MAC 密钥。最终输出为 (R, c, t),即临时公钥、密文和认证标签。
以 P-256 曲线搭配 AES-128-GCM 为例,我们可以精确地描述「线上传输的到底是哪些字节」。临时公钥 R 在未压缩格式下为 65 字节(0x04 前缀 + 32 字节 x 坐标 + 32 字节 y 坐标),若使用压缩格式则为 33 字节(0x02 或 0x03 前缀 + 32 字节 x 坐标)。密文 c 的长度与明文完全相同,因为 AES-GCM 在 CTR 模式下逐字节异或,不引入填充。认证标签 t 固定为 16 字节(128 位)。因此,对于一条 100 字节的明文,未压缩格式下的总传输开销为 65 + 100 + 16 = 181 字节,压缩格式下为 33 + 100 + 16 = 149 字节。如果换用 X25519 + ChaCha20-Poly1305,临时公钥仅 32 字节,密文等长于明文,标签同样 16 字节,总开销进一步降低。理解这些具体数值有助于在协议设计中准确地规划消息格式和带宽预算。
解密过程是对称的操作。接收方收到 (R, c, t) 后,首先验证 R 是椭圆曲线上的有效点(这一步对于防止无效曲线攻击至关重要)。然后用自己的私钥计算共享秘密点 S’ = d_R * R = d_R * r * G = S。由 ECDH 的数学性质保证,发送方和接收方计算出的共享秘密是相同的。接下来用同样的 KDF 导出密钥,验证 MAC 标签(或 AEAD 标签),最后解密密文得到明文。
从 KEM/DEM 视角来看,ECIES 的 KEM 部分恰好是”ECDH + KDF”:Encaps 生成临时密钥对、执行 ECDH、通过 KDF 导出对称密钥。DEM 部分则是标准的对称认证加密。这种分解使得 ECIES 的安全性分析变得格外清晰。在间隙 Diffie-Hellman(Gap Diffie-Hellman, GDH)假设和随机预言机模型下,ECIES-KEM 可以被证明是 IND-CCA2 安全的。
ECIES 的一个重要实现细节是点验证。接收方在使用接收到的临时公钥 R 之前,必须验证它确实是所选椭圆曲线上的一个合法点,且不是小子群中的点。如果跳过这一验证,攻击者可以精心构造处于其他曲线(无效曲线)上的点,通过多次交互逐步恢复接收方的私钥。这就是著名的无效曲线攻击(Invalid Curve Attack)。使用 X25519 等蒙哥马利曲线可以在很大程度上规避这一风险,因为其运算天然地将输入映射到正确的群上。
五、HPKE(RFC 9180)
混合公钥加密(Hybrid Public Key Encryption, HPKE)是由 IETF 在 RFC 9180 中标准化的现代混合加密框架,于 2022 年发布。它汲取了 ECIES 的设计精髓,同时在灵活性、安全性和标准化程度上做出了显著提升。HPKE 已被 TLS Encrypted Client Hello(ECH)、消息层安全协议(Message Layer Security, MLS)、Oblivious HTTP(OHTTP)等新一代互联网协议所采用,正在迅速成为混合加密的事实标准。
笔者认为,HPKE 极有可能成为未来混合加密的默认原语。原因在于,这是密码学界第一次拥有一个同时覆盖认证模式(Base/PSK/Auth/AuthPSK)、密钥调度、多消息加密和密钥导出的单一、完整、算法敏捷的框架。回顾过去,ECIES 虽然思想优秀,但其规范分散在 IEEE 1363a、SEC 1、ISO 18033-2 等多个互不兼容的标准中,不同标准在 KDF 输入格式、点编码方式、MAC 计算范围等细节上各执一词,导致实现者不得不反复查阅规范并做出容易出错的选择。HPKE 的设计从一开始就以消除误用为核心目标——内部管理随机数序列号、强制绑定上下文信息、提供清晰的 API 语义——这些特性使得整类常见的密码学误用从接口层面就被排除。当一个标准既足够灵活又足够安全,它就有条件成为「不需要理由就使用」的默认选项。
HPKE 的架构由三个可协商的密码学原语组成:KEM(密钥封装机制)、KDF(密钥派生函数)和 AEAD(认证加密与关联数据)。一个 HPKE 密码套件(Ciphersuite)由这三个组件的具体实例共同确定,例如 DHKEM(X25519, HKDF-SHA256) + HKDF-SHA256 + AES-128-GCM。
HPKE 定义了四种操作模式,以满足不同的认证需求:
Base 模式是最基本的模式,仅提供加密功能,不提供发送方认证。发送方使用接收方的公钥执行 KEM 封装操作,导出共享密钥,然后用 AEAD 加密数据。接收方可以确信只有自己能解密消息,但无法确认消息来自哪个发送方。
PSK 模式在 Base 模式的基础上引入了预共享密钥(Pre-Shared Key)。双方事先共享一个对称密钥 psk 和一个标识符 psk_id。PSK 被混入密钥调度过程中,因此只有同时持有接收方私钥和 PSK 的一方才能解密。这提供了一种轻量级的发送方认证手段。
Auth 模式提供基于公钥的发送方认证。发送方在 KEM 封装操作中同时使用自己的私钥和接收方的公钥,生成的共享秘密同时绑定了双方的身份。接收方在解封装时使用自己的私钥和发送方的公钥,从而确认消息确实来自声称的发送方。
AuthPSK 模式是 Auth 模式与 PSK 模式的结合,同时提供公钥认证和预共享密钥认证,达到最高的安全保证。
HPKE 的密钥调度(Key Schedule)过程将 KEM 输出的共享秘密、模式标识、PSK(如有)、以及可选的应用层信息(info 字段)一同输入 KDF,导出加密密钥(key)、基础随机数(base_nonce)和导出器秘密(exporter_secret)。base_nonce 与一个内部序列号(seq)进行异或运算,为每次 AEAD 加密提供唯一的随机数(nonce),从而支持在同一个 HPKE 上下文中安全地加密多条消息,而无须外部提供随机数。
导出功能(Export)是 HPKE 的一个额外特性:通过 exporter_secret 和一个应用层提供的上下文字符串,可以派生出任意长度的密钥材料,用于 AEAD 加密之外的用途,例如为关联协议派生额外的对称密钥。
下面用 Go 代码展示 HPKE Base 模式的基本用法:
package main
import (
"crypto/rand"
"fmt"
"log"
"github.com/cloudflare/circl/hpke"
)
func main() {
// 选择 HPKE 密码套件:DHKEM(X25519) + HKDF-SHA256 + AES-128-GCM
kemID := hpke.KEM_X25519_HKDF_SHA256
kdfID := hpke.KDF_HKDF_SHA256
aeadID := hpke.AEAD_AES128GCM
suite := hpke.NewSuite(kemID, kdfID, aeadID)
// 接收方生成密钥对
publicKey, privateKey, err := kemID.Scheme().GenerateKeyPair()
if err != nil {
log.Fatalf("密钥生成失败: %v", err)
}
// 应用层信息,绑定到密钥调度中
info := []byte("hybrid-encryption-demo")
// === 发送方:封装并加密 ===
sender, err := suite.NewSender(publicKey, info)
if err != nil {
log.Fatalf("创建发送方失败: %v", err)
}
// Encaps: 生成 KEM 封装密文 enc 和加密上下文
enc, sealer, err := sender.Setup(rand.Reader)
if err != nil {
log.Fatalf("封装失败: %v", err)
}
// 加密明文
plaintext := []byte("混合加密将公钥密码与对称密码完美结合")
aad := []byte("associated-data")
ciphertext, err := sealer.Seal(plaintext, aad)
if err != nil {
log.Fatalf("加密失败: %v", err)
}
fmt.Printf("封装密文 (enc): %x\n", enc)
fmt.Printf("AEAD 密文长度: %d 字节\n", len(ciphertext))
// === 接收方:解封装并解密 ===
receiver, err := suite.NewReceiver(privateKey, info)
if err != nil {
log.Fatalf("创建接收方失败: %v", err)
}
opener, err := receiver.Setup(enc)
if err != nil {
log.Fatalf("解封装失败: %v", err)
}
decrypted, err := opener.Open(ciphertext, aad)
if err != nil {
log.Fatalf("解密失败: %v", err)
}
fmt.Printf("解密明文: %s\n", decrypted)
_ = privateKey // 确保 privateKey 被使用
}这段代码展示了 HPKE 的典型使用流程:接收方生成密钥对并公布公钥;发送方使用公钥创建发送方上下文并执行封装操作,获得封装密文 enc 和一个 Sealer(用于 AEAD 加密);发送方通过 Sealer 加密明文后,将 enc 和 AEAD 密文一并发送;接收方使用私钥和 enc 创建接收方上下文并获得 Opener(用于 AEAD 解密),最终恢复明文。整个过程中,密钥调度、随机数管理等细节均由 HPKE 库内部处理,极大地降低了误用风险。
六、DHKEM 详解
DHKEM(Diffie-Hellman KEM)是 HPKE 中定义的默认 KEM 构造,也是当前使用最广泛的 KEM 实例。它将经典的 Diffie-Hellman 密钥交换协议转化为满足 KEM 接口的密钥封装机制,支持 X25519、X448、P-256 和 P-521 等多种椭圆曲线群。
在非认证(Base/PSK)模式下,DHKEM 的封装操作(Encap)工作如下:发送方生成一个临时密钥对 (ek_s, dk_s),其中 ek_s 是临时公钥,dk_s 是临时私钥。然后计算 DH 共享秘密 dh = DH(dk_s, pk_R),其中 pk_R 是接收方的公钥。最后,将 dh 以及双方公钥信息输入 ExtractAndExpand 函数(基于 HKDF),导出最终的共享秘密 shared_secret。封装密文 enc 就是发送方的临时公钥 ek_s 的序列化。
解封装操作(Decap)中,接收方从 enc 中恢复发送方的临时公钥 ek_s,然后用自己的私钥计算 dh = DH(sk_R, ek_s)。由 DH 的交换律保证 DH(dk_s, pk_R) = DH(sk_R, ek_s),因此双方导出相同的 shared_secret。
在认证(Auth/AuthPSK)模式下,DHKEM 的封装操作增加了一步额外的 DH 计算。发送方同时计算两个共享秘密:dh1 = DH(dk_s, pk_R)(临时密钥与接收方公钥)和 dh2 = DH(sk_S, pk_R)(发送方静态私钥与接收方公钥)。两个 DH 结果被拼接后一起输入 ExtractAndExpand,导出最终的 shared_secret。这样,shared_secret 同时依赖于发送方的长期私钥,从而实现发送方认证:只有持有发送方私钥 sk_S 的一方才能生成正确的 shared_secret。
对应的认证解封装(AuthDecap)中,接收方计算 dh1 = DH(sk_R, ek_s) 和 dh2 = DH(sk_R, pk_S),同样拼接后输入 ExtractAndExpand。
DHKEM 的一个关键设计决策是将双方公钥编码到 KDF 的输入中(通过 kem_context 参数)。这确保了共享秘密与具体的公钥绑定,防止了身份误绑定攻击(Identity Misbinding Attack):即攻击者无法将一个合法的封装密文”重新绑定”到另一个接收方。
一个经常被忽视的观点是,DHKEM 与传统 ECIES 在密钥派生上的差异远比表面看起来更深刻。ECIES 的典型实现直接从原始 DH 共享秘密点(通常是其 x 坐标)调用 KDF 导出密钥,输入中往往不包含任何上下文信息。而 HPKE 的 DHKEM 引入了一套完整的密钥调度(Key Schedule),将模式标识(mode)、预共享密钥(psk)、应用层信息字符串(info)以及双方公钥全部混入 KDF 的输入。这条密钥调度链正是阻止跨协议攻击(Cross-Protocol Attack)和身份误绑定的关键防线——如果没有它,同一个 DH 计算结果可能在不同的协议上下文中被视为合法,攻击者便可利用这种歧义性发起攻击。从工程实践来看,ECIES 各标准(IEEE 1363a、SEC 1、ISO 18033-2)在 KDF 输入的具体格式上各不相同,这种碎片化本身就是安全隐患的温床;HPKE 通过统一且严格的密钥调度规范,从根本上消除了这一类问题。
值得注意的是,DHKEM 中临时密钥的新鲜性(Freshness)至关重要。如果临时私钥 dk_s 被重用或可预测,整个方案的安全性将崩塌。因此,临时密钥必须使用高质量的随机数生成器来产生。RFC 9180 还提供了一个确定性封装接口(用于测试目的),但明确警告不得在生产环境中使用固定的随机性。
七、RSA-KEM vs ECIES-KEM
在 KEM 范式下,除了基于椭圆曲线 DH 的 ECIES-KEM(或 DHKEM)之外,基于 RSA 的 RSA-KEM 同样是一个标准化的构造。RSA-KEM 的设计理念甚至比传统的 RSA-OAEP 加密更为简洁。
RSA-KEM 的封装操作如下:随机选择一个整数 z,满足 0 < z < n(n 为 RSA 模数),计算封装密文 c = z^e mod n(e 为公钥指数),然后用 KDF 从 z 导出对称密钥 k = KDF(z)。注意,这里并没有对”给定的明文”进行 RSA 加密——z 是随机生成的,密文 c 就是 z 的 RSA 加密结果,而对称密钥由 z 经 KDF 导出。解封装时,接收方计算 z = c^d mod n(d 为私钥指数),再用 KDF 导出 k。
RSA-KEM 的优势在于其安全性证明异常简洁。在 RSA 假设(不是更强的 RSA-OAEP 所需的随机预言机假设)和适当的 KDF 假设下,RSA-KEM 即可被证明是 IND-CCA2 安全的。相比之下,RSA-OAEP 的安全性证明需要随机预言机模型,且曾在标准模型中遇到困难。
然而,RSA-KEM 在实践中面临严重的性能劣势。2048 位 RSA 密钥的封装密文为 256 字节,而 X25519 DHKEM 的封装密文仅 32 字节,差距达 8 倍。在计算速度上,RSA 的模幂运算也显著慢于椭圆曲线的标量乘法。更关键的是,等效安全强度下 RSA 需要更长的密钥:128 位安全强度对应 3072 位 RSA 模数或仅 256 位的椭圆曲线参数。
密钥长度方面的差距在移动设备、物联网(IoT)和带宽受限的环境中尤为显著。此外,RSA-KEM 不支持像 DHKEM 那样自然地实现发送方认证(Auth 模式),因为 RSA 不具备 DH 那样的交换律特性。
基于以上原因,现代混合加密方案和协议(如 HPKE、TLS 1.3)几乎一致地偏好基于椭圆曲线的 KEM。RSA-KEM 虽然在理论上优雅,在实际部署中更多地作为历史遗留方案存在。不过,RSA-KEM 的设计思想——将公钥加密”退化”为纯粹的密钥封装,消除对填充方案的复杂依赖——深刻地影响了后续 KEM 标准化的方向。
八、KEM 的形式化安全性
KEM 的标准安全性定义是 IND-CCA2(在自适应选择密文攻击下的不可区分性)。这个安全游戏的形式如下:
挑战者运行 KeyGen 生成公钥 pk 和私钥 sk,将 pk 交给攻击者。然后挑战者运行 Encaps(pk) 得到 (c, k_0),同时随机采样一个同分布的密钥 k_1。挑战者随机选择比特 b,将 (c, k_b) 交给攻击者。攻击者可以访问解封装预言机 Decaps(sk, ·),但不得查询挑战密文 c*。最终攻击者输出对 b 的猜测 b’。KEM 的 IND-CCA2 优势定义为 |Pr[b’ = b] - 1/2|。
这个定义比传统公钥加密的 IND-CCA2 定义更简洁,因为 KEM 不需要处理”挑战明文”的选择——密钥和封装密文由 Encaps 算法共同生成,攻击者的任务仅仅是区分真实密钥和随机密钥。
KEM 的 IND-CCA2 安全性与传统公钥加密(PKE)的 IND-CCA2 安全性之间存在紧密的联系。一方面,任何 IND-CCA2 安全的 PKE 方案都可以自然地构造一个 IND-CCA2 安全的 KEM:Encaps 随机采样密钥 k,然后用 PKE 加密 k。另一方面,通过 KEM/DEM 组合定理,IND-CCA2 安全的 KEM 与一次性 IND-CCA 安全的 DEM 组合后,得到的混合加密方案是 IND-CCA2 安全的 PKE。
KEM/DEM 组合定理的精确表述如下:设 KEM 的 IND-CCA2 优势为 epsilon_KEM,DEM 的一次性 IND-CCA 优势为 epsilon_DEM,则组合方案的 IND-CCA2 优势最多为 epsilon_KEM + epsilon_DEM。这是一个紧致的归约(Tight Reduction),意味着组合后安全性的损失仅为两个组件安全性的简单相加,不会因为组合而引入额外的指数级退化。
这个紧致性是 KEM/DEM 范式相比早期混合加密构造的核心优势之一。在早期的某些混合方案中,归约的损失可能依赖于解密查询的数量,导致具体安全参数难以精确估计。KEM/DEM 范式的紧致组合定理使得安全参数的选择变得清晰透明。
在实际应用中,DEM 的安全性通常由成熟的 AEAD 算法(如 AES-GCM、ChaCha20-Poly1305)提供,其安全性被广泛研究和认可。因此,混合方案的整体安全性主要取决于 KEM 组件。这进一步强调了 KEM 作为独立密码原语的重要性——它是连接公钥世界与对称密钥世界的关键桥梁,其安全性直接决定了整个加密通信的安全水平。
九、后量子 KEM 与 HPKE 的未来
量子计算的发展对当前基于离散对数和大整数分解的公钥密码体系构成了根本性威胁。Shor 算法能够在量子计算机上以多项式时间破解 RSA、ECDH 和 ElGamal 等方案,这意味着基于这些困难问题的 KEM(RSA-KEM、DHKEM)在量子时代将不再安全。因此,密码学社区正在积极开发和标准化后量子 KEM(Post-Quantum KEM)。
2024 年 8 月,美国国家标准与技术研究院(NIST)正式发布了 ML-KEM(Module-Lattice-based Key Encapsulation Mechanism)标准,即 FIPS 203。ML-KEM 基于模格(Module Lattice)上的 Learning With Errors(LWE)问题,提供三个安全级别的参数集:ML-KEM-512(大致对应 128 位经典安全强度)、ML-KEM-768(192 位)和 ML-KEM-1024(256 位)。ML-KEM 的前身是 CRYSTALS-Kyber,经过多轮国际评估后被选为 NIST 后量子密码标准化竞赛的最终胜出者。
ML-KEM 的封装密文和公钥尺寸虽然比椭圆曲线方案大(ML-KEM-768 的公钥为 1184 字节,封装密文为 1088 字节,而 X25519 的公钥和封装密文均为 32 字节),但在后量子方案中已属极为紧凑。其计算性能也相当优秀——在现代 CPU 上,ML-KEM 的封装和解封装速度甚至比 RSA-2048 更快,与 X25519 处于同一数量级。
将 ML-KEM 集成到 HPKE 框架中是当前 IETF 标准化工作的重点方向之一。draft-westerbaan-cfrg-hpke-xyber768d00 等草案提出了在 HPKE 中使用后量子 KEM 的方案。一个关键的过渡策略是混合 KEM(Hybrid KEM),即在同一个 HPKE 实例中同时使用一个传统 KEM(如 DHKEM(X25519))和一个后量子 KEM(如 ML-KEM-768),将两者的共享秘密组合后输入密钥调度。这种混合策略确保了即使其中一个 KEM 被攻破(无论是传统方案被量子计算机攻破,还是后量子方案被发现新的经典攻击),整体安全性仍然得到保障。
X-Wing 是一个具体的混合 KEM 提案,它将 X25519 和 ML-KEM-768 组合为一个单一的 KEM 原语。X-Wing 的设计目标是提供一个”即插即用”的后量子安全 KEM,可以直接替换 HPKE 中的 DHKEM(X25519),而不需要对 HPKE 的密钥调度或 AEAD 部分做任何修改。Chrome 浏览器已经在 TLS 1.3 中实验性地部署了类似的混合方案(ML-KEM-768 + X25519),对延迟和带宽的影响经实测在可接受范围内。
展望未来,HPKE 的 KEM 敏捷性设计使其能够平滑地过渡到后量子时代。随着 ML-KEM 标准的成熟和更多后量子 KEM 候选方案(如基于编码理论的 HQC,已在 NIST 第四轮中作为备选方案继续评估)的标准化,HPKE 只需注册新的 KEM 标识符即可支持新的算法,而 KDF 和 AEAD 组件保持不变。这正是 KEM/DEM 范式模块化设计的终极体现——面对密码学基础假设的根本性变迁,我们只需替换一个组件,整座大厦依然稳固。
对于工程团队而言,当前的务实建议是:在新系统中优先采用 HPKE 作为混合加密方案的基础框架,默认使用 DHKEM(X25519) + HKDF-SHA256 + ChaCha20-Poly1305 或 AES-256-GCM 密码套件,并为未来切换到混合后量子 KEM 预留算法协商接口。在安全性要求极高且面临长期数据保护需求的场景(如政府通信、医疗档案、金融长期存储)中,可以考虑立即部署混合 KEM(X25519 + ML-KEM-768),以防范”先存储、后解密”(Harvest Now, Decrypt Later)的量子威胁。
密码学百科系列 · 第 20 篇