3. AES算法原理与性能特征
AES(Advanced Encryption Standard)是当前最广泛使用的对称分组密码算法,支持128/192/256位密钥长度,分组大小固定为128位。理解AES的算法原理与性能特征,是后续进行加解密性能调优的基础。
3.1 AES-128/192/256加解密流程
AES加密过程由多轮迭代组成,每轮包含四个基本操作:SubBytes、ShiftRows、MixColumns和AddRoundKey。不同密钥长度对应的轮数不同:
| AES变体 | 密钥长度 | 轮数 | 最后一轮特殊处理 |
|---|---|---|---|
| AES-128 | 128 bit (16 byte) | 10 | 跳过MixColumns |
| AES-192 | 192 bit (24 byte) | 12 | 跳过MixColumns |
| AES-256 | 256 bit (32 byte) | 14 | 跳过MixColumns |
解密流程与加密对称,使用逆操作:InvSubBytes、InvShiftRows、InvMixColumns和AddRoundKey。解密时轮密钥的使用顺序与加密相反。
3.2 轮函数详解
AES每轮由四个变换组成,每个变换都有明确的数学定义和性能特征:
3.2.1 SubBytes(字节代换)
使用16×16的S盒对状态矩阵中的每个字节进行非线性替换。S盒是AES安全性的核心,但查表操作在软件中可能引发缓存侧信道攻击。
3.2.2 ShiftRows(行移位)
对状态矩阵的每一行进行循环左移:第0行不移,第1行移1字节,第2行移2字节,第3行移3字节。该操作仅涉及字节索引重排,计算开销极低。
3.2.3 MixColumns(列混合)
将状态矩阵的每一列视为GF(2⁸)上的多项式,与固定多项式相乘。该操作是AES中最耗时的部分之一,涉及有限域乘法和异或运算。
3.2.4 AddRoundKey(轮密钥加)
将状态矩阵与轮密钥进行逐字节异或。该操作计算量小,但需要频繁访问轮密钥数组。
3.3 密钥扩展
密钥扩展(Key Expansion)从原始密钥生成所有轮密钥。AES-128需要11个轮密钥(包含初始密钥),AES-192需要13个,AES-256需要15个。
密钥扩展的核心操作包括:
- RotWord:将4字节字循环左移1字节。
- SubWord:对4字节字应用S盒替换。
- Rcon:与轮常数进行异或。
密钥扩展的计算量远小于加解密本身,但在密钥频繁更换的场景(如每个数据包使用不同密钥)中,密钥扩展可能成为瓶颈。
3.4 软件实现中的性能热点
在纯软件实现中,AES的性能瓶颈主要集中在以下几个方面:
| 性能热点 | 原因分析 | 优化方向 |
|---|---|---|
| S盒查表 | SubBytes需要256次查表/轮,查表延迟高且可能触发缓存未命中 | 使用位切片技术、SIMD查表、预计算T表 |
| MixColumns有限域乘法 | GF(2⁸)乘法涉及条件分支和移位操作,计算密集 | 使用T表合并SubBytes和MixColumns、SIMD并行化 |
| 轮密钥加载 | 每轮需要加载16字节轮密钥,内存访问频繁 | 将轮密钥缓存到寄存器、使用展开循环减少加载次数 |
| 数据依赖链 | 每轮结果必须等待上一轮完成,难以指令级并行 | 多块并行处理(CTR/GCM模式天然支持)、流水线化 |
| 解密性能劣于加密 | InvMixColumns比MixColumns更复杂,且需要额外计算 | 使用等效解密密钥、预计算逆T表 |
3.5 性能基准数据
以下为典型软件实现(无硬件加速)在3.0GHz x86-64处理器上的单线程吞吐量参考值:
| AES变体 | 加密吞吐量 | 解密吞吐量 | 密钥扩展耗时 |
|---|---|---|---|
| AES-128 | ~800 MB/s | ~650 MB/s | ~0.5 μs |
| AES-192 | ~680 MB/s | ~550 MB/s | ~0.7 μs |
| AES-256 | ~580 MB/s | ~470 MB/s | ~0.9 μs |
3.6 代码示例:AES-128单块加密核心循环
// AES-128加密核心循环(C语言风格伪代码)
void aes128_encrypt(uint8_t state[16], const uint8_t round_keys[11][16]) {
uint8_t i;
// 初始轮密钥加
add_round_key(state, round_keys[0]);
// 第1~9轮
for (i = 1; i <= 9; i++) {
sub_bytes(state); // S盒替换
shift_rows(state); // 行移位
mix_columns(state); // 列混合
add_round_key(state, round_keys[i]); // 轮密钥加
}
// 第10轮(无MixColumns)
sub_bytes(state);
shift_rows(state);
add_round_key(state, round_keys[10]);
}
从代码可见,AES-128的10轮循环中,第1~9轮执行4个操作,第10轮执行3个操作。性能优化应重点关注sub_bytes和mix_columns函数的实现效率。