目录
[一、核心问题:state 既是输入,也是输出?](#一、核心问题:state 既是输入,也是输出?)
[二、state 到底是什么?(AES 核心结构)](#二、state 到底是什么?(AES 核心结构))
[三、你这段代码:AES 解密流程 逐行讲解](#三、你这段代码:AES 解密流程 逐行讲解)
[四、最关键:state 全程在被修改!](#四、最关键:state 全程在被修改!)
[AES 加密 / 解密流程图](#AES 加密 / 解密流程图)
[一、先记住:state 永远是 4×4 矩阵](#一、先记住:state 永远是 4×4 矩阵)
[二、AES 加密流程(正向)](#二、AES 加密流程(正向))
[三、AES 解密流程(你代码里的逻辑)](#三、AES 解密流程(你代码里的逻辑))
[四、加密 vs 解密对比图(最关键)](#四、加密 vs 解密对比图(最关键))
[五、一句话总结 state 的一生](#五、一句话总结 state 的一生)

State矩阵
state矩阵,即使输入也是输出?
static void aes_xcrypt(state_t *state, const uint8 *round_key, boolean decrypt)
{
if (decrypt)
{
aes_add_round_key(state, AES_ROUNDS, round_key);
for (uint32 i = 0;; i++)
{
aes_shift_rows(state, TRUE);
aes_substitute_bytes(state, TRUE);
aes_add_round_key(state, AES_ROUNDS - 1 - i, round_key);
if (i == AES_ROUNDS - 1)
{
break;
}
aes_mix_columns(state, TRUE);
}
}
一、核心问题:state 既是输入,也是输出?
state_t *state 是一个指针,指向一块内存:
- 调用函数时:你把待加密 / 解密的数据放进 state 里 → 这是输入
- 函数执行完:state 里的数据被改写成加密 / 解密后的结果 → 这是输出
它不是 "传值",而是直接修改内存里的内容,所以同一个变量,既是入参,也是出参。
二、state 到底是什么?(AES 核心结构)
AES 处理的不是零散字节,而是一个 4×4 的字节矩阵:
state[0][0] state[0][1] state[0][2] state[0][3]
state[1][0] state[1][1] state[1][2] state[1][3]
state[2][0] state[2][1] state[2][2] state[2][3]
state[3][0] state[3][1] state[3][2] state[3][3]
- 一共 16 字节(AES 分组固定大小)
- state_t 就是这个 4×4 矩阵的类型定义
- 所有 AES 变换(行移位、字节代换、列混合、轮密钥加)全部都在操作这个矩阵
三、你这段代码:AES 解密流程 逐行讲解
这段代码是 AES 解密核心函数(decrypt = TRUE 分支)。
完整逻辑(标准 AES-128 解密)
static void aes_xcrypt(state_t *state, const uint8 *round_key, boolean decrypt)
{
if (decrypt) // 进入解密模式
{
// 1. 先和【最后一轮密钥】异或(初始轮密钥加)
aes_add_round_key(state, AES_ROUNDS, round_key);
// 2. 循环执行 AES 轮函数(共 AES_ROUNDS 轮,通常 10 轮)
for (uint32 i = 0;; i++)
{
// 逆行移位(解密专用,反向移动行)
aes_shift_rows(state, TRUE);
// 逆字节代换(解密用 S 盒逆表)
aes_substitute_bytes(state, TRUE);
// 轮密钥加:使用第 (AES_ROUNDS-1-i) 轮密钥
aes_add_round_key(state, AES_ROUNDS - 1 - i, round_key);
// 循环终止条件:执行完所有轮次退出
if (i == AES_ROUNDS - 1)
{
break;
}
// 逆列混合(最后一轮不执行)
aes_mix_columns(state, TRUE);
}
}
}
每一步在干嘛?
- aes_add_round_key
把 state 矩阵和轮密钥做异或(AES 必用操作)。
- aes_shift_rows(TRUE)
解密:逆行移位(把行移回去)。
- aes_substitute_bytes(TRUE)
解密:逆字节代换(用逆 S 盒查表)。
- aes_mix_columns(TRUE)
解密:逆列混合(最后一轮不做)。
四、最关键:state 全程在被修改!
整个函数没有任何返回值,所有结果都写回 *state:
- 进来:state = 密文
- 出去:state = 明文
这就是 AES 实现里最经典的 in-place 就地运算。
五、一句话总结(最核心)
- state 是 AES 的 4×4 数据矩阵
- 它是指针,所以既是输入,也是输出
- 函数所有操作都直接修改这块内存
- 解密完成后,原数据被覆盖为解密结果
总结
- state 既是输入也是输出,因为它是指针,函数直接修改内存里的数据。
- state 本质是 16 字节的 4×4 矩阵,AES 所有变换都围绕它进行。
- 你这段代码是 AES 解密流程,按 "逆操作" 还原数据。
- 函数无返回值,结果全部写回 state。
AES 加密 / 解密流程图
下面给你画最清晰、最直观的 AES 加密 / 解密流程图,专门围绕你这段代码里的 state 变化来讲。
一、先记住:state 永远是 4×4 矩阵
[ 0] [ 4] [ 8] [12]
[ 1] [ 5] [ 9] [13]
[ 2] [ 6] [10] [14]
[ 3] [ 7] [11] [15]
所有操作都在原地修改这个矩阵。
二、AES 加密流程(正向)
整体结构
- 初始轮密钥加
- state ⊕ 第 0 轮密钥
- 循环 Nr−1 轮(Nr=10 轮 for AES-128)
- 字节代换 SubBytes
- 行移位 ShiftRows
- 列混合 MixColumns
- 轮密钥加 AddRoundKey
- 最后一轮(无列混合)
- 字节代换 SubBytes
- 行移位 ShiftRows
- 轮密钥加 AddRoundKey
流程图(文字版)
明文 → [state]
↓
AddRoundKey (轮0)
↓
┌─────────────────────┐
│ SubBytes │
│ ShiftRows │
│ MixColumns │
│ AddRoundKey (轮i) │ ← 循环 Nr-1 次
└─────────────────────┘
↓
SubBytes
ShiftRows
AddRoundKey (轮Nr)
↓
密文 ← [state]
三、AES 解密流程(你代码里的逻辑)
整体结构
解密是逆序 + 逆操作
- 先和最后一轮密钥异或
- state ⊕ 第 Nr 轮密钥
- 循环 Nr 轮
- 逆行移位 InvShiftRows
- 逆字节代换 InvSubBytes
- 轮密钥加 AddRoundKey(从后往前取)
- 不是最后一轮才做:逆列混合 InvMixColumns
对应你代码的流程图
密文 → [state]
↓
AddRoundKey (轮Nr)
↓
┌─────────────────────────┐
│ InvShiftRows │
│ InvSubBytes │
│ AddRoundKey (轮Nr-1-i) │
│ │
│ if (不是最后一轮) │
│ InvMixColumns │ ← 循环 Nr 次
└─────────────────────────┘
↓
明文 ← [state]
四、加密 vs 解密对比图(最关键)
表格
| 步骤 | AES 加密(正向) | AES 解密(逆向) |
|---|---|---|
| 初始 | AddRoundKey (轮 0) | AddRoundKey (轮 Nr) |
| 主体循环 | SubBytes → ShiftRows → MixColumns → AddRoundKey | InvShiftRows → InvSubBytes → AddRoundKey → InvMixColumns |
| 轮密钥顺序 | 0 → 1 → 2 → ... → Nr | Nr → Nr−1 → ... → 0 |
| 最后一轮 | 无 MixColumns | 无 InvMixColumns |
| state | 输入明文 → 输出密文 | 输入密文 → 输出明文 |
五、一句话总结 state 的一生
- 加密时state
进去是明文,出来是密文。
- 解密时state
进去是密文,出来是明文。
- 全程不复制、不返回、就地修改
→ 所以它既是输入,也是输出。