3. AES-128的T表实现与内存占用权衡

AES-128的T表实现与内存占用权衡 学习卡片

T表法的核心思想

AES-128的轮函数由SubBytes、ShiftRows、MixColumns、AddRoundKey四步组成。查表法需要分别执行S盒替换、行移位和列混合,而T表法把前三步合并为一次32位查表操作:将状态矩阵的每一列作为索引,从4张256项的32位表中取出4个值,异或后直接得到该列经过SubBytes+ShiftRows+MixColumns的结果。

设状态矩阵按列存储为 s[0..3](每列4字节),T表法的单列变换可写为:

// Te0[x] = [S[x]*2, S[x], S[x], S[x]*3] 的32位打包
// Te1[x] = [S[x]*3, S[x]*2, S[x], S[x]]
// Te2[x] = [S[x], S[x]*3, S[x]*2, S[x]]
// Te3[x] = [S[x], S[x], S[x]*3, S[x]*2]
// 其中乘法为GF(2^8)上的xtime运算

// 单列变换(加密方向)
t0 = Te0[s[0]>>24] ^ Te1[(s[1]>>16)&0xFF] ^
     Te2[(s[2]>>8)&0xFF]  ^ Te3[s[3]&0xFF] ^ rk[0];
t1 = Te0[s[1]>>24] ^ Te1[(s[2]>>16)&0xFF] ^
     Te2[(s[3]>>8)&0xFF]  ^ Te3[s[0]&0xFF] ^ rk[1];
t2 = Te0[s[2]>>24] ^ Te1[(s[3]>>16)&0xFF] ^
     Te2[(s[0]>>8)&0xFF]  ^ Te3[s[1]&0xFF] ^ rk[2];
t3 = Te0[s[3]>>24] ^ Te1[(s[0]>>16)&0xFF] ^
     Te2[(s[1]>>8)&0xFF]  ^ Te3[s[2]&0xFF] ^ rk[3];

注意索引的错位:s[1]取第2字节、s[2]取第3字节、s[3]取第4字节,这正是ShiftRows在列方向上的体现。最后一轮不做MixColumns,因此需要单独使用S盒表Te4(或直接查S盒)并配合轮密钥异或。

T表法单列变换:SubBytes + ShiftRows + MixColumns 合并为一次查表 输入状态列 s[0..3] s[0] = b0 b1 b2 b3 s[1] = b4 b5 b6 b7 s[2] = b8 b9 ba bb s[3] = bc bd be bf 每列4字节,共4列 按列优先存储 T表查表(4张256项32位表) Te0 [2,1,1,3] Te1 [3,2,1,1] Te2 [1,3,2,1] Te3 [1,1,3,2] 索引:s[0]高字节 → Te0,s[1]次高字节 → Te1 s[2]次低字节 → Te2,s[3]低字节 → Te3 每张表 256 × 4B = 1KB,4张共 4KB 查表结果异或后得到变换列 输出变换列 t[0..3] t0 = Te0^Te1^Te2^Te3 ^ rk0 t1 = Te0^Te1^Te2^Te3 ^ rk1 t2 = Te0^Te1^Te2^Te3 ^ rk2 t3 = Te0^Te1^Te2^Te3 ^ rk3 4次查表 + 4次异或 完成一列变换 查表法 vs T表法:速度与RAM占用对比(示例MCU:Cortex-M0+ @48MHz,无硬件AES) 对比项 查表法(S盒+列混合) T表法(4张32位表) ROM占用 S盒256B + 列混合表约1KB 4张表共4KB(Te0~Te3) RAM占用 状态16B + 临时变量约8B 状态16B + 临时变量约8B 单轮指令数(估算) 约 120~160 条 约 60~80 条 速度(相对) 基准 1.0× 约 1.8× ~ 2.2× 注:以上为教学估算值,实际取决于编译器优化、Flash等待周期和MCU架构

在MCU上的实现要点

T表法的关键实现细节:

  • 表生成:Te0~Te3可在编译期由S盒和GF(2^8)乘法生成,也可在运行时初始化。若Flash紧张,可只存Te0和S盒,运行时推导其余表,但会增加启动时间。
  • 字节序处理:T表按32位字存储,索引时需注意大小端。Cortex-M默认小端,s[0]>>24取的是最高字节,与表定义一致。
  • 最后一轮:第10轮不做MixColumns,需用Te4(S盒的32位扩展)或直接查S盒,再异或轮密钥。
  • 解密方向:解密需用逆T表Td0~Td3,或采用等价解密结构复用加密表,但会改变轮密钥顺序。
若MCU的Flash充足(≥8KB)且追求速度,T表法是首选;若Flash极度受限(如仅2KB),查表法或位运算实现更合适。实际选型时建议用arm-none-eabi-size对比两种实现的.text和.data段大小。

验证与测量方法

用NIST AES-128标准测试向量验证正确性:

明文: 00112233445566778899aabbccddeeff
密钥: 000102030405060708090a0b0c0d0e0f
密文: 69c4e0d86a7b0430d8cdb78070b4c55a

速度测量:在GPIO引脚翻转前后各置一次,用示波器测高电平持续时间,除以加密次数得到单次耗时。RAM占用通过.map文件查看.bss和.data段变化。