一句话版本
实际的加密系统几乎从不直接用 RSA 或椭圆曲线去加密一整个文件,因为它们又慢、又有长度限制。标准做法是混合加密,也叫信封加密:随机生成一把对称密钥加密数据(快),再用接收者的公钥把这把对称密钥"封"起来(安全地交给对方)。 它由三个零件组成:非对称(交付钥匙)、对称(加密数据并防篡改)、哈希 / 密钥派生(把共享秘密变成合格的钥匙)。HTTPS、PGP 邮件、云服务的 KMS、libsodium 的 sealed box,结构都是这样。
全文分三层:
- 通俗理解:把钥匙放进信封
- 实际用处:云 KMS、PGP、HPKE、浏览器端加密
- 原理与工程要点:ECDH + HKDF + AEAD 的完整流程、大文件分块、常见错误
第一层:通俗理解
1.1 把钥匙放进信封
你要寄一箱贵重物品给朋友:
- 买一把新挂锁,把箱子锁上(对称加密数据,又快又能锁大东西);
- 把这把挂锁的钥匙放进一个只有朋友能拆的特制信封(用朋友的公钥加密这把小钥匙);
- 箱子和信封一起寄出。
朋友拆开信封拿到钥匙,再打开箱子。途中任何人都拿不到钥匙,也就打不开箱子。
1.2 为什么不直接用公钥加密整个文件
| 非对称(RSA、椭圆曲线) | 对称(AES、ChaCha20) | |
|---|---|---|
| 速度 | 慢,每次运算都是大数或曲线运算 | 极快,有硬件加速 |
| 能加密多长 | RSA 一次只能加密比密钥短的数据 | 任意长 |
| 擅长 | 让陌生人之间安全地交付一个小秘密 | 加密大量数据 |
所以各取所长:非对称只负责那几十个字节的钥匙,对称负责剩下的一切。
第二层:实际用处
| 场景 | 怎么用信封加密 |
|---|---|
| 云服务 KMS(AWS KMS、Google Cloud KMS 等) | 数据用"数据密钥"(DEK)加密,DEK 再用 KMS 里的"主密钥"(KEK)加密后和数据存在一起。主密钥从不离开 KMS |
| PGP / GPG 邮件 | 随机会话密钥加密邮件正文,再用每个收件人的公钥分别加密会话密钥 |
| HTTPS | 握手时用(EC)DH 协商出共享秘密,派生出对称密钥加密之后的流量 |
| HPKE(RFC 9180,2022) | 把"KEM + 密钥派生 + AEAD"标准化成一个通用构件,被 TLS 的加密客户端问候(ECH)、MLS 群聊协议等采用 |
| 浏览器端加密上传 | 浏览器用服务器所有者的公钥加密文件后上传,服务器只存密文,只有持有私钥的人能解开 |
轮换主密钥变得很便宜:换主密钥时,只要把每个 DEK 重新封一次(每个只有几十字节),不需要把 TB 级的数据全部重新加密。这是云服务普遍采用信封加密的重要原因。
第三层:原理与工程要点
3.1 基于 ECDH 的完整流程
接收者事先生成一对长期密钥:私钥 ,公钥 。
发送方:
- 生成一对临时密钥 、;
- 计算共享秘密 (ECDH,见《Diffie–Hellman与离散对数》、椭圆曲线);
- 用 HKDF 从 派生出对称密钥 ;
- 用 AEAD(如 AES-GCM、ChaCha20-Poly1305)和随机 nonce 加密数据,得到密文和认证标签;
- 发送 。
接收方:用自己的私钥算 ,派生出同一个 ,解密并验证标签。
只看到 和 的旁观者,要算出 就得解椭圆曲线离散对数问题。
3.2 为什么需要 HKDF
ECDH 得到的共享秘密 是曲线上一个点的坐标,它不是均匀随机的比特串(比如它一定满足曲线方程),不能直接当 AES 密钥。HKDF 分两步:
- 提取(extract):用 HMAC 把不均匀的输入"搅匀"成一个伪随机密钥;
- 扩展(expand):结合
info参数(如"某应用 v1 文件加密")派生出所需长度的密钥。
info 参数还能做域分离:同一个共享秘密,给不同用途派生出互不相关的密钥。
3.3 为什么要 AEAD
只加密不认证是不够的:攻击者虽然读不懂密文,但可能改动它,让解密结果按他的意图变化(见《一次一密》 里的可延展性)。AEAD(带关联数据的认证加密)在加密的同时生成一个认证标签,密文被改动一个比特,解密就会直接失败。
3.4 大文件:分块加密
把一个几 GB 的录音一次性读进内存加密不现实。标准做法:
- 随机生成一把内容密钥,用信封方式封起来;
- 用这把内容密钥对文件分块做 AEAD,每块带序号,最后一块带"结束"标记;
- 序号和结束标记防止攻击者重排、删除或截断数据块。
libsodium 的 secretstream 接口就是这样设计的,可以边录边加密。
3.5 常见错误
| 错误 | 后果 |
|---|---|
| 同一把密钥下重复使用 nonce(AES-GCM) | 灾难性:两条明文的异或泄露,认证也能被伪造 |
| 用 RSA 但不加 OAEP 填充 | 教科书式 RSA 可被多种方式攻破(见《RSA与欧拉定理》) |
| 共享秘密直接当密钥,不做 KDF | 密钥分布不均匀,也没有域分离 |
| 只加密不认证 | 密文可被篡改 |
| 不检查对方公钥是否合法 | 小子群攻击(见《Diffie–Hellman与离散对数》) |
所以实践中最稳妥的选择是使用高层封装(libsodium 的 sealed box、HPKE 库、云 KMS 的 SDK),而不是自己拼装底层原语。
信封加密不自动带来前向保密
如果接收方始终用同一把长期私钥 ,那么 一旦泄露,所有历史上收到的信封都能被打开。这是"必须能事后解密"的存储场景的固有代价,详见《前向保密》。
总结
| 层次 | 要点 |
|---|---|
| 直觉 | 对称锁箱子,非对称封钥匙 |
| 三个零件 | 非对称(ECDH / RSA-OAEP)、KDF(HKDF)、AEAD(AES-GCM / ChaCha20-Poly1305) |
| 好处 | 快、能加密任意长度、换主密钥只需重封 DEK |
| 实践 | 用高层封装;nonce 绝不重复;大文件分块并防截断 |