加密模式详解:GCM、CBC、CTR 等模式对比
直接对数据进行块加密,会暴露数据的统计规律。所以我们需要加密模式——把块加密算法套在某个模式里,变成流式或分组的安全方案。我个人最早做对象存储加密时,对这些模式也是一头雾水,后来踩了几个坑才真正搞明白。今天咱们就把 CBC、CTR、GCM 这三个最常用的模式拆开看。
CBC 模式——密码分组链接
CBC 的原理很简单:每个明文块先和上一个密文块做 XOR,然后再用密钥加密。第一个块需要一个初始向量(IV)。
- 加密必须顺序执行,无法并行
- 解密可以并行(前提是有所有密文块)
- 一个密文块损坏,会影响后续块解密(错误扩散)
CBC 的加密过程就是一条链——加密器必须等前一块处理完才能继续。这也是为什么它在 GPU 或多核环境里比较吃亏。不过解密可以并行,因为密文块本身就能拿到。
CTR 模式——计数器模式
CTR 把块密码变成了流密码。用一个每次加 1 的计数器配合密钥生成密钥流,然后直接和明文 XOR。解密也一样:生成相同的密钥流 XOR 密文。
- 加密和解密都能完全并行
- 支持随机访问——想解密第 N 块,直接生成第 N 块的密钥流就行
- 没有错误扩散:一个密文块错了,只有那块数据受影响
我记得有个对象存储项目,用户要求能随机读取大文件的任意字节。CBC 做不到,因为你需要从头解密到目标位置。CTR 轻松搞定——你只需要知道文件开始处的计数器值,就可以直接跳到指定位置生成密钥流。这个特性在对象存储里太实用了。
但 CTR 有个致命要求:计数器值(IV+nonce)不能重复使用。一旦重复,两个密文块 XOR 一下就能消掉密钥流,明文直接暴露。
必须用原子递增的计数器或者 UUID 级 nonce。
GCM 模式——Galois/计数器模式
GCM 是 CTR 的升级版。它在 CTR 加密的基础上,增加了一个 GMAC 认证标签,用于校验数据完整性。简单说:GCM = CTR + 认证。
- 加密和认证一步到位,不需要额外计算 HMAC
- 支持 AAD(附加认证数据),比如加密文件时可以同时认证文件名、时间戳
- 硬件加速友好(Intel AES-NI + PCLMULQDQ)
我个人习惯:只要系统支持 AES-NI,我优先选 GCM。比如对象存储的桶加密、客户端加密,GCM 几乎成了事实标准。AWS S3 的 SSE-C 就是用的 GCM。
GCM 的 nonce 长度推荐 96 位(12 字节),这也是性能最优的长度。如果 nonce 长度不是 96 位,内部会增加一次额外的 GHASH 计算,性能会下降 10%–30%。
三种模式对比
| 属性 | CBC | CTR | GCM |
|---|---|---|---|
| 加密并行 | 否 | 是 | 是 |
| 解密并行 | 是 | 是 | 是 |
| 随机访问支持 | 否 | 是 | 是 |
| 错误扩散 | 2 块以上 | 仅当前块 | 仅当前块 |
| 认证完整性 | 无 | 无 | 有 (GMAC) |
| 常见场景 | 磁盘加密、遗留系统 | 流加密、随机读对象 | 对象存储、网络传输 |
| 性能(AES-NI) | 中等 | 高 | 高 |