# AES-GCM 与 AES-CBC 对比：应该选择哪种模式？

> 从安全性、认证能力、IV 要求、性能和兼容性对比 AES-GCM 与 AES-CBC，帮助新旧系统选择正确的加密模式。

Canonical: https://hsmkit.com/zh/guides/aes-gcm-vs-cbc/

Last updated: 2026-09-22

AES-GCM 和 AES-CBC 都以 AES 分组密码为基础，但二者提供的安全保证不同。GCM 是面向现代系统的认证加密模式；CBC 只提供机密性，必须额外配合消息认证码（MAC）。本文从安全性、IV 要求、性能与兼容性出发，说明新旧系统应该如何选择。

## 结论先行

除非现有协议或旧系统强制要求 CBC，**新应用应优先选择 AES-GCM**。GCM 在一次操作中同时完成加密和完整性认证；CBC 本身只能加密，如果没有正确构造 MAC，攻击者可能在不被发现的情况下修改密文。

只有在必须兼容旧格式，并且采用**先加密、后认证（Encrypt-then-MAC）**且加密密钥与认证密钥相互独立时，CBC 才是合理选择。

## 安全能力对比

| 特性 | AES-GCM | AES-CBC |
|---|---|---|
| 机密性 | 有 | 有 |
| 完整性与真实性 | 内置认证标签 | 不提供 |
| 是否需要填充 | 不需要 | 通常需要 PKCS#7 |
| IV / Nonce 长度 | 推荐 12 字节 Nonce | 16 字节 IV |
| IV 要求 | 同一密钥下永不重复 | 随机且不可预测 |
| 并行加密 | 支持 | 不支持 |
| 常见故障 | Nonce 重用 | 缺少 MAC、填充预言机、可预测 IV |
| 新系统建议 | 推荐 | 仅用于兼容 |

密钥长度不会改变模式层面的安全性质。没有认证的 AES-256-CBC，仍然比使用唯一 Nonce 的 AES-128-GCM 更容易被错误使用。

## 为什么必须认证密文

加密用于隐藏明文，但不一定能证明密文来自可信发送方。主动攻击者可能翻转、删除、重新排列或替换字节，应用必须在使用数据前识别这些改动。

GCM 会随密文产生认证标签，通常为 128 位。只有密钥、Nonce、密文、标签以及可选的附加认证数据（AAD）全部匹配时，解密才会成功。

CBC 没有认证标签。安全的 CBC 方案通常使用独立认证密钥，对版本、IV 和密文计算 HMAC：

```text
密文 = AES-CBC-Encrypt(加密密钥, IV, 填充后明文)
标签 = HMAC(认证密钥, 版本 || IV || 密文)
```

接收方必须在尝试 CBC 解密**之前**验证标签。自行设计 Encrypt-and-MAC 或 MAC-then-Encrypt 很容易产生细微漏洞，应优先使用经过审查的协议或库。

## IV 与 Nonce 要求

### GCM Nonce

NIST 推荐 GCM 使用 96 位（12 字节）Nonce。Nonce 不需要保密，但在同一密钥下绝不能重复。重复会泄露明文之间的关系，并可能破坏认证能力。

中低消息量系统可以使用密码学安全随机源生成 12 字节 Nonce。高吞吐或分布式系统应设计无冲突的计数器方案。详细故障分析见 [AES IV 与 Nonce 重用](/zh/guides/aes-iv-nonce-reuse/)。

### CBC IV

CBC 需要新的 16 字节 IV，而且攻击者在选择明文前不能预测该值。应使用密码学安全随机数生成器，并将 IV 与密文一同存储或传输；IV 无需保密。

不要用时间戳、记录 ID、上一个 IV、密码或明文哈希派生 CBC IV。可预测 IV 会泄露首个明文分组之间的关系。

## 性能与消息长度

GCM 支持并行处理，通常可以利用现代 CPU、TLS、浏览器 Web Crypto 和密码库的硬件加速。典型输出开销为：

- 12 字节 Nonce；
- 与明文等长的密文；
- 16 字节认证标签。

CBC 加密是串行的，因为每个明文分组依赖前一个密文分组。它还会增加 1–16 字节 [PKCS#7 填充](/zh/guides/pkcs7-padding-aes/)、16 字节 IV；安全实现还需要额外的 MAC。

对短消息来说，协议开销比 AES 运算速度更重要；对大数据流来说，GCM 的并行能力通常更有优势。

## 兼容性场景

以下情况可能仍要求 CBC：

- 旧文件或数据库格式；
- 老旧支付、企业协议；
- 无法协商 AEAD 算法的系统；
- 迁移期间仍需解密的历史数据。

兼容性不能成为使用未认证加密的理由。如果旧格式无法容纳 MAC，应将其视作明确风险，并设计带版本的新格式，而不是继续扩展旧格式。

GCM 已广泛支持于 OpenSSL、Java、.NET、Web Crypto、Node.js、Go、Python 主流密码库及云密钥管理服务。

## 从 CBC 迁移到 GCM

安全迁移需要明确区分新旧记录：

```text
版本 || 算法 || Nonce或IV || 密文 || 认证标签
```

推荐步骤：

1. 在数据封装中加入版本或算法标识；
2. 新数据使用 GCM 和全新 Nonce；
3. 暂时保留已认证 CBC 历史数据的读取能力；
4. 历史数据认证、解密成功后重新加密为 GCM；
5. 停止写入 CBC，保留期结束后再移除 CBC 读取。

不要通过密文长度猜测算法。明确版本可以避免降级攻击和解析歧义。

## 选择清单

适合选择 GCM 的情况：

- 设计新协议或存储格式；
- 需要认证加密；
- 平台提供成熟 GCM 实现；
- 能保证 Nonce 唯一。

只有满足以下条件时才使用 CBC：

- 兼容性强制要求；
- 使用 Encrypt-then-MAC 认证密文；
- 加密与 MAC 密钥独立派生；
- 对外不区分填充错误和认证错误；
- IV 来自安全随机源。

## 在线验证模式差异

使用 [AES 加密工具](/aes-encryption) 对比 CBC 与其他模式，观察 IV 与填充行为。浏览器开发者可继续阅读 [Web Crypto AES-GCM 指南](/zh/guides/web-crypto-aes-gcm/)。在线工具只应使用测试数据，切勿粘贴生产密钥或敏感明文。
