代码实现源码(python版+C版)## 摘要
本文以 FIPS 197 为准绳,从算法原理、软实现、安全芯片驱动、侧信道防护、国际认证五个维度,完整解析 AES 的软件实现。给出可运行的Python 参考实现(aes.py)与C 驱动(aes_.c),后者在逆运算校验基础上,进一步实现掩码 S 盒、常数时间查表、随机延时流控三层侧信道防护。全部代码通过 FIPS 197 附录 B/C 标准测试向量验证。
关键词:AES、FIPS 197、软实现、侧信道攻击、DPA、掩码、安全芯片、SOG-IS、GF(2⁸)
一、为什么 AES 的软实现比 DES 更值得讲
承接前一篇 DES 软实现,AES 与之有本质结构差异,这决定了实现难度与防护策略完全不同:
| 特性 | DES | AES |
|---|---|---|
| 结构 | Feistel(L/R 半区互换) | SPN(替代-置换网络) |
| 解密 | 子密钥逆序(“免费”) | 完整逆变换链(逆 S 盒/逆 ShiftRows/逆 MixColumns) |
| 非线性 | 8 个 6→4 bit S 盒 | 1 个 8→8 bit S 盒(GF(2⁸) 逆元+仿射) |
| 密钥 | 56 bit(已可破解) | 128/192/256 bit |
| 分组 | 64 bit | 128 bit |
核心结论:AES 解密不能"免费",必须独立实现一套逆变换,这是软实现最容易出错、也最考验功底的地方。
二、算法原理(FIPS 197 要点)
2.1 四个轮变换
加密每轮四步:
- SubBytes:字节经 S 盒替换(唯一非线性);
- ShiftRows:第 r 行循环左移 r 字节;
- MixColumns:每列左乘固定矩阵(GF(2⁸) 域运算,列间扩散);
- AddRoundKey:与轮密钥逐字节异或。
首轮只 AddRoundKey;末轮省略 MixColumns。
2.2 GF(2⁸) 有限域——AES 的数学心脏
AES 的 S 盒与 MixColumns 都建立在 GF(2⁸) 上,不可约多项式为:
m(x) = x⁸ + x⁴ + x³ + x + 1 (即 0x11B)这是整个实现正确性的根基。MixColumns 的01/02/03、逆矩阵的09/0b/0d/0e,全靠它做乘法。
2.3 S 盒的构造
S 盒是 AES 唯一的非线性环节,本质是GF(2⁸) 乘法逆元 + 仿射变换。实现时逆 S 盒由 S 盒程序化生成,避免手工抄写 256 项易错:
SBOX=[0x63,0x7c,0x77,0x7b,...]# FIPS 197 图 7INV_SBOX=[0]*256foriinrange(256):INV_SBOX[SBOX[i]]=i# 由 S 盒反推逆 S 盒2.4 密钥编排(Key Expansion)
密钥按 4 字节成字w[i],i≥Nk时:若i mod Nk==0则对w[i-1]做RotWord→SubWord→异或 Rcon;AES-256 时i mod Nk==4额外 SubWord。生成Nr+1个 128 bit 轮密钥:
三、Python 实现核心片段
3.1 有限域乘法
MixColumns 的02倍乘本质是「左移 + 条件异或 0x11B」,即_xtime;通用乘法_gmul则在其上叠加循环:
def_xtime(a):# x 倍(×2)a<<=1ifa&0x100:a^=0x11B# 溢出则模不可约多项式returna&0xFFdef_gmul(a,b):# 通用乘法(MixColumns 用)r=0for_inrange(8):ifb&1:r^=a hi=a&0x80a=(a<<1)&0xFFifhi:a^=0x1Bb>>=1returnr3.2 解密逆变换链(SPN 与 DES 的本质差异)
AES 解密是严格逆序的完整逆变换:先AddRoundKey(末轮密钥),中间轮按InvShiftRows → InvSubBytes → AddRoundKey → InvMixColumns顺序,末轮无 InvMixColumns。这与 DES「子密钥逆序免费解密」截然不同——必须独立实现逆 S 盒、逆 ShiftRows、逆 MixColumns。
模块调用关系如下:
3.3 密钥编排
defkey_expansion(key):nk=len(key)//4nr={4:10,6:12,8:14}[nk]# 密钥长度驱动轮数w=[[key[4*i+j]forjinrange(4)]foriinrange(nk)]foriinrange(nk,4*(nr+1)):temp=w[i-1][:]ifi%nk==0:temp=_sub_word(_rot_word(temp))temp[0]^=RCON[i//nk-1]elifnk>6andi%nk==4:# AES-256 特有temp=_sub_word(temp)w.append([w[i-nk][j]^temp[j]forjinrange(4)])...3.4 单块加密(末轮无 MixColumns)
单块加密数据流如下图所示(首轮 AddRoundKey → 中间 Nr−1 轮完整四步 → 末轮省 MixColumns):
defaes_encrypt_block(block16,key):rks=key_expansion(key);nr=len(rks)-1state=_add_round_key(block16,rks[0])forrndinrange(1,nr):state=_sub_bytes(state,SBOX)state=_shift_rows(state)state=_mix_columns(state)state=_add_round_key(state,rks[rnd])state=_sub_bytes(state,SBOX)# 末轮省略 MixColumnsstate=_shift_rows(state)state=_add_round_key(state,rks[nr])returnstate3.5 自测:FIPS 197 附录 B/C 三档向量
AES-128: key=000102...0f0f PT=001122...eeff → 69c4e0d86a7b0430d8cdb78070b4c55a AES-192: key=000102...1717 PT=001122...eeff → dda97ca4864cdfe06eaf70a0ec0d7191 AES-256: key=000102...1f1f PT=001122...eeff → 8ea2b7ca516745bfeafc49904b496089运行python aes.py,三档全部通过。
四、C 驱动与侧信道防护
aes_.c在 DES 驱动基础上,构建三层侧信道防护:
4.1 逆运算校验(抗故障注入)
staticse_statusaes_encrypt_block_secure(constuint8_tin[16],uint8_tout[16],constuint8_t*rks,intnr){/* ... 加密 ... *//* 逆运算校验:解密回明文比对 */uint8_tback[16];aes_decrypt_block(s,back,rks,nr);if(memcmp(back,in,16)!=0)returnSE_FALSE;memcpy(out,s,16);returnSE_TRUE;}4.2 常数时间掩码 S 盒(抗缓存侧信道)
/* 全表扫描 + 掩码选通:无数据依赖的访存地址差异 */staticuint8_tsbox_masked_ct(uint8_tidx){uint8_tr=0;for(inti=0;i<256;i++){uint8_tmatch=(uint8_t)(0xFFu*(uint8_t)(idx==i));r|=SBOX[i]&match;}returnr;}4.3 随机延时流控(抗 SPA)
staticvoidrandom_delay(void){volatileuint32_td=rng_next()&0x3F;while(d--){asmvolatile("":::"memory");}}统一入口AES_Crypto_drv通过mode位域(bit14 逆校验、bit13 掩码、bit12 延时)开关防护,ECB/CBC、AES-128/192/256 全支持。
4.4 算法实现关键点小结
- SPN 结构与逆变换链:解密需独立逆 S 盒、逆 ShiftRows、逆 MixColumns,不可像 DES 那样子密钥逆序了事。
- GF(2⁸) 域运算:
0x11B不可约多项式是 MixColumns/InvMixColumns 的正确性根基,_gmul/_xtime是实现核心。 - 末轮无 MixColumns:加密与解密的末轮均省略列混合,最易漏。
- 逆 S 盒程序化生成:避免手工 256 项抄写错误。
- 密钥长度驱动轮数:Nk=4/6/8 对应 Nr=10/12/14,Rcon 索引随轮数延伸。
- KAT 自测:FIPS 197 附录 B/C 三档向量是最低验证门槛。
五、抗侧信道攻击分析
5.1 计时攻击 / 缓存侧信道(Cache-Timing)
| 泄漏点 | 位置 | 防护手段 |
|---|---|---|
| S 盒查表索引依赖密钥 | SBOX[state[i]] | 常数时间查表(sbox_masked_ct);或 bitslicing |
| MixColumns 分支 | gmul的 if | 改为常数时间(无数据依赖分支) |
5.2 功耗分析(SPA/DPA)
| 泄漏点 | 位置 | 防护手段 |
|---|---|---|
| S 盒输出汉明重量与功耗相关 | SubBytes | 布尔掩码(sub_bytes_masked) |
| 轮密钥异或功耗模式 | AddRoundKey | 掩码 + 随机化 |
5.3 故障注入攻击(FA)
| 泄漏点 | 位置 | 防护手段 |
|---|---|---|
| 轮次/中间位可被翻转 | 各轮变换 | 逆运算校验(已实现)、冗余计算 |
六、侧信道防护全景
| 防护目标 | 手段 | 状态 |
|---|---|---|
| 计时/缓存侧信道 | 常数时间查表 | ✅ 已实现 |
| DPA(功耗) | 一阶布尔掩码 | ✅ 已实现 |
| SPA(时序) | 随机延时流控 | ✅ 已实现 |
| 故障注入 | 逆运算校验 | ✅ 已实现 |
| 高阶 DPA | 高阶掩码/双轨逻辑 | ⚠️ 需硬件 |
| 密钥生命周期 | 安全存储+用后清零 | ⚠️ 待补充 |
纯软件掩码是必要不充分条件,完整抗侧信道需芯片硬件(TRNG、双轨逻辑、屏蔽层)协同。密钥目前以明文传入,生产落地需改为安全存储 + 用后清零。
七、认证对照
| 认证体系 | 与 AES 的关系 |
|---|---|
| EMVCo | AES 取代 TDES 用于支付 MAC/加密 |
| EUCC / SOG-IS | AES-128/192/256 是 SOG-IS认可对称算法;pp0084 要求密码机制硬件化 |
| GB/T 22186-2016 | IC 卡芯片安全技术要求,对应 CC 国标映射 |
| 现行标准 | FIPS 197(本体);SP 800-38A(模式);SP 800-90A(随机数) |
八、总结
- AES 是SPN 结构,解密需完整逆变换链,这是与 DES(Feistel)最大的实现差异。
- GF(2⁸) 域运算(0x11B)是正确性根基,MixColumns/InvMixColumns 全靠它。
- C 驱动实现「逆运算校验 + 掩码 S 盒 + 随机延时流控」三层侧信道防护,相对 DES 是显著增量。
- 生产落地优先 AES-256 + 硬件密码引擎;软实现用于教学、算法验证与驱动参考。
代码实现链接:见链接