密语 · CIPHER | 目录 CH.07 / 26
绝密
Phase 2 · 对称密码

分组密码 AES

全世界的默认加密算法。把它拆开,你会看到混淆与扩散被打磨成一台精密的四步机器。

阅读 ~16 分钟 前置 第 3、5 章 Demo AES-128 逐轮状态矩阵

当你的 App 调用 Cipher.getInstance("AES/GCM/NoPadding")、当你连上 HTTPS、当你的磁盘被加密——底层跑的很可能都是 AES。它是 2001 年由 NIST 从公开竞赛中选出的标准,二十多年来经受住了全球密码学家的围攻,至今没有实际可行的攻击。这一章我们把这台机器拆开看。

一、分组密码:一次锁一块

和流密码逐字节处理不同,分组密码一次加密固定大小的一整块。AES 的块大小是 128 位 = 16 字节。它有三种密钥长度:AES-128、AES-192、AES-256。我们以最常用的 AES-128 为例。

AES 属于 SPN(代换-置换网络)结构:把明文块反复地"代换"(制造混淆)和"置换/混合"(制造扩散),做很多轮(round)。AES-128 做 10 轮。第 3 章埋下的混淆与扩散,在这里被具体化成四个操作。

状态矩阵(State)

AES 把 16 字节的块排成一个 4×4 的字节矩阵,叫状态(State)。注意排列是按列填充的:第 1 个字节在 (行0,列0),第 2 个在 (行1,列0)……填满一列再下一列。之后所有操作都在这个 4×4 矩阵上进行。下面的 Demo 会全程把这个矩阵画给你看。

二、四个轮变换

每一轮(除首尾略有出入)依次做四件事:

① SubBytes —— 混淆的核心

把矩阵里每个字节通过一张固定的查找表(S-盒)替换成另一个字节。S-盒不是随便造的:它基于有限域 GF(2⁸) 里的求逆再加一个仿射变换,专门设计成高度非线性——这是 AES 对抗差分/线性分析的主力。它就是第 3 章说的"混淆":让密文和密钥的关系复杂到无法用线性方法逼近。

② ShiftRows —— 让字节跨列流动

把矩阵的第 0 行不动、第 1 行循环左移 1 格、第 2 行移 2 格、第 3 行移 3 格。单看很简单,作用是让原本待在同一列的字节散到不同列去。

③ MixColumns —— 扩散的核心

把每一当作 GF(2⁸) 上的一个多项式,乘以一个固定矩阵。效果是:这一列的每个输出字节都依赖于该列的全部 4 个输入字节。配合上一步的 ShiftRows,仅仅两轮之后,任何一个输入字节的改动就会波及整个 16 字节块。这就是第 3 章说的"扩散",也是雪崩效应(第 10 章)的来源。(最后一轮省略 MixColumns,是为了让加密和解密结构对称。)

④ AddRoundKey —— 把密钥混进来

把当前状态和"轮密钥"逐字节 XOR。轮密钥由原始密钥经密钥扩展算法派生,每轮一把、各不相同。绕了一圈,加密里唯一真正用到密钥的地方,还是我们第 5 章的老朋友——XOR。

为什么要 10 轮?

一轮的混淆+扩散不够彻底,攻击者能顺着结构往回推。多轮层层叠加,才让密文彻底"熟透"。AES-128 的 10 轮是安全裕度与性能的折中——已知的最好攻击也只能啃动其中 7 轮左右,离 10 轮还有可观的安全余量。轮数不是拍脑袋定的,是被密码分析"逼"出来的。

三、单步走完一次 AES 加密

下面的 Demo 用真正的 AES-128(教学实现,已用 FIPS-197 官方测试向量校验)加密你输入的一个 16 字节块。点"下一步",逐个操作地走,观察 4×4 状态矩阵如何变化;发生改变的字节会高亮。特别留意:走到第 1~2 轮的 MixColumns 之后,矩阵已经面目全非——这就是扩散的力量。

DEMO AES-128 逐轮状态矩阵
矩阵按列填充(左上→左下→右上)。每个操作后,发生变化的格子会短暂标红。走到最后一步,下方十六进制就是最终密文。

四、AES 有多结实

暴力破解 AES-128 需要平均尝试 2¹²⁷ 个密钥。给个尺度:即使有一台每秒能试 10¹⁸ 次(远超今天任何超算)的机器,试完也要约 10²¹ 年——宇宙年龄的一千亿倍。AES-256 更是把这个数字平方。只要密钥是真随机的,直接破 AES 在物理上不可行

所以现实中针对 AES 系统的攻击,几乎从不去碰算法本身,而是打它的周边:

你几乎永远不该自己实现 AES

本章的 Demo 是为"看清内部"而写的教学实现,它不是常数时间的,存在缓存时间侧信道,绝不可用于生产。真实项目请用平台库:Android 上是 javax.crypto.Cipher(底层走 Conscrypt / 硬件 AES-NI),浏览器里是 WebCrypto。第 20 章会给出正确的 Kotlin 用法。理解原理是为了会用、会判断,不是为了重造轮子。

但请记住:AES 只加密一个 16 字节块。你要加密的数据几乎总是长于 16 字节——那多个块之间怎么衔接?这个看似琐碎的问题,藏着密码学史上最著名的一张翻车图。下一章见分晓。

本章要点

  • AES 是分组密码,块大小 16 字节,采用 SPN 结构;AES-128 做 10 轮。
  • 四个轮变换:SubBytes(S-盒,混淆)、ShiftRows + MixColumns(扩散)、AddRoundKey(XOR 轮密钥)。
  • 两轮之后单字节改动即扩散至整块——雪崩效应的根源。
  • 直接暴力破 AES 物理上不可行;真实攻击打的是密钥来源、模式选择与侧信道,而非算法。