4、分组密码工作模式:从ECB到GCM

分组密码本身只处理固定长度的数据块,比如AES一次加密16字节。但实际数据哪有这么规整?你想想看,一个文件、一张图片、一段视频,长度都是随机的。所以我们需要工作模式——说白了,就是一套规则,告诉你怎么用同一个密钥反复调用分组密码,把任意长度的数据安全地加密完。

我这些年做安全方案评审,见过不少因为选错工作模式导致的安全事故。今天我把六种主流模式掰开揉碎讲清楚,每种模式我都会说它的原理、适用场景,以及我踩过的坑。

核心观点:工作模式的选择直接影响安全性。选错了,算法再强也没用。

分组密码工作模式分类总览 分组密码工作模式 ECB · 电子密码本 CBC · 密码分组链接 CFB · 密文反馈 OFB · 输出反馈 CTR · 计数器 GCM · 伽罗瓦计数器 模式选择建议 • 不要用ECB——它不安全,除非你只是加密随机密钥 • 日常首选GCM(认证加密),其次CTR或CBC

4.1 ECB模式——最直观,也最危险

ECB(Electronic Codebook)的原理简单到离谱:把明文切成一块一块,每块独立加密。就像用一本密码本,查表替换。

// ECB加密伪代码
for each block in plaintext:
    ciphertext_block = AES_encrypt(block, key)

听起来很完美对吧?但问题来了——相同的明文块会生成相同的密文块。这意味着什么?

我举个例子。如果你加密一张企鹅图片,ECB模式加密后,你仍然能看出企鹅的轮廓。因为图像中颜色相同的区域被加密成了相同的密文块,图案信息根本没被隐藏。

⚠ 安全警告:ECB模式不适合加密结构化数据。我在一次代码审计中看到有人用ECB加密JSON数据包,攻击者通过观察密文块重复就能推断出数据字段的边界和重复值。这是典型的ECB模式误用。

ECB唯一合理的用途是加密随机数据,比如密钥本身。因为随机数据没有重复模式,ECB的弱点不会暴露。

4.2 CBC模式——引入随机化

CBC(Cipher Block Chaining)解决了ECB的核心问题。它让每个明文块在加密前先与前一个密文块做异或运算。第一个块没有前驱,就用一个随机初始向量(IV)。

// CBC加密伪代码
ciphertext[0] = AES_encrypt(plaintext[0] XOR IV, key)
for i = 1 to n:
    ciphertext[i] = AES_encrypt(plaintext[i] XOR ciphertext[i-1], key)

这样一来,相同的明文块因为位置不同、前驱密文不同,加密结果完全不同。图像加密后就是纯粹的噪声。

我个人习惯在文件加密场景中使用CBC模式。但要注意几个坑:

  • IV必须随机且不可预测。我曾经见过有人用固定IV,结果相同的明文前缀产生了相同的密文前缀,泄露了数据模式。
  • CBC不能并行加密。每个块依赖前一个块的输出,加密是串行的。但解密可以并行,因为解密只需要前一个密文块。
  • 填充攻击。CBC要求明文长度是块大小的整数倍,需要填充。如果填充校验不当,可能被Padding Oracle攻击。

💡 实战建议:使用CBC时,IV必须是每次加密随机生成的,长度等于块大小(AES为16字节)。IV不需要保密,但必须保证唯一性。我通常把IV直接拼在密文前面一起传输。

4.3 CFB模式——把分组密码变成流密码

CFB(Cipher Feedback)的思路是把AES当做一个伪随机数生成器来用。它加密的不是明文,而是前一个密文块,然后用输出与明文异或得到当前密文。

// CFB加密伪代码
feedback = IV
for each block in plaintext:
    output = AES_encrypt(feedback, key)
    ciphertext_block = plaintext_block XOR output
    feedback = ciphertext_block

CFB的好处是不需要填充——你可以只取输出的一部分与明文异或,实现任意长度的加密。这在加密流式数据时很实用。

但CFB也有弱点:加密是串行的,而且如果密文在传输中损坏,会影响后续所有块的解密。我记得有一次调试网络协议加密,就因为一个字节的传输错误,导致整个后续数据全部乱码。

4.4 OFB模式——预计算密钥流

OFB(Output Feedback)和CFB很像,但反馈的是加密输出本身,而不是密文。这意味着你可以提前计算出整个密钥流,然后与明文异或。

// OFB加密伪代码
feedback = IV
for each block in plaintext:
    output = AES_encrypt(feedback, key)
    ciphertext_block = plaintext_block XOR output
    feedback = output  // 注意:反馈的是output,不是密文

OFB最大的优势是:密钥流可以预计算。如果你知道要加密1GB数据,可以先把1GB的密钥流算好存着,后面加密就是简单的异或操作,速度极快。

但OFB有个致命问题:如果IV重复,整个密钥流就重复了。两个不同的明文用相同的密钥流加密,攻击者可以通过异或两个密文直接得到明文的异或值,进而破解。

关键点:OFB和CTR模式都要求IV/计数器绝对不能重复。一旦重复,安全归零。我在设计密钥管理系统时,会强制使用递增计数器+随机前缀来保证唯一性。

4.5 CTR模式——并行之王

CTR(Counter)模式是目前最实用的流密码模式之一。它用一个递增的计数器值作为输入,加密后与明文异或。计数器从IV开始,每加密一个块就加1。

// CTR加密伪代码
counter = IV
for i = 0 to n:
    keystream = AES_encrypt(counter + i, key)
    ciphertext[i] = plaintext[i] XOR keystream

CTR模式有几个突出的优点:

  • 完全并行。每个块的密钥流只依赖计数器的值,可以同时计算所有块的密钥流。现代CPU的AES-NI指令集配合CTR模式,速度极快。
  • 不需要填充。最后一个块可以只取需要的密钥流长度。
  • 随机访问。你可以直接解密第100个块,不需要先解密前99个。这在加密数据库或磁盘时非常有用。

我参与过一个高性能加密网关项目,最终选型就是AES-CTR。单机吞吐量轻松达到10Gbps以上。但CTR模式本身不提供完整性保护,需要配合MAC使用。

4.6 GCM模式——认证加密的标杆

GCM(Galois/Counter Mode)是CTR模式的升级版。它在CTR加密的基础上,增加了伽罗瓦域上的认证标签计算,同时提供机密性和完整性保护。

// GCM加密伪代码(简化)
// 1. 使用CTR模式加密
ciphertext = AES_CTR_encrypt(plaintext, key, nonce)

// 2. 计算认证标签
auth_tag = GHASH(additional_data, ciphertext) XOR AES_encrypt(nonce || counter_0, key)

GCM的核心优势:

  • 一次操作完成加密+认证。不需要先加密再算HMAC,性能更好。
  • 支持附加数据(AAD)。可以认证那些不需要加密的头部信息,比如IP包头的源地址。
  • 硬件加速友好。现代CPU和网卡都支持GCM的硬件加速。

⚠ 重要提醒:GCM的nonce(相当于IV)长度通常为12字节。nonce绝对不能重复使用。如果同一个密钥下nonce重复,攻击者不仅可以破解加密,还能伪造认证标签。我在一次安全培训中反复强调:GCM的nonce管理是安全的第一道防线。

4.7 模式对比与选型指南

模式 加密并行 解密并行 需要填充 完整性保护 典型场景
ECB ✅ ✅ ✅ ❌ 加密随机密钥
CBC ❌ ✅ ✅ ❌ 文件加密、数据库加密
CFB ❌ ❌ ❌ ❌ 流式数据加密
OFB ❌ ❌ ❌ ❌ 预计算密钥流场景
CTR ✅ ✅ ❌ ❌ 高性能加密、磁盘加密
GCM ✅ ✅ ❌ ✅ 网络协议、TLS、API加密

💡 我的选型建议:

  • 新项目默认选GCM。它同时提供加密和认证,安全性最高。
  • 如果环境不支持GCM硬件加速,选CTR + 独立的MAC(如HMAC-SHA256)。
  • 文件加密场景可以用CBC,但一定要加MAC。
  • 永远不要在生产环境使用ECB加密结构化数据。

4.8 实战中的常见陷阱

我这些年做安全审计,总结出几个高频踩坑点:

  1. IV/Nonce重用。这是最致命的问题。无论CBC、CTR还是GCM,IV重复都会导致安全崩溃。我曾经审计过一个物联网平台,所有设备用同一个密钥和固定IV加密数据,结果攻击者直接破解了整个系统的通信。
  2. 忽略认证。只加密不认证,等于没保护。攻击者可以篡改密文,解密后得到恶意数据。GCM模式就是为了解决这个问题而设计的。
  3. 填充Oracle攻击。CBC模式如果填充校验不当,攻击者可以通过观察服务器是否返回填充错误来逐字节破解密文。解决方案是使用认证加密模式,或者确保填充校验不泄露任何信息。
  4. 密钥和IV混淆。有人把IV当密钥用,或者把密钥当IV用。密钥必须保密,IV不需要保密但必须唯一。两者角色完全不同。

嗯,到这里六种模式的核心内容就讲完了。每种模式都有自己的脾气,选对了事半功倍,选错了后患无穷。我个人建议,如果你不确定选哪个,GCM是最稳妥的选择——它把加密和认证打包在一起,安全性经过广泛验证,性能也足够好。