第3节 SM4对称密码算法原理归纳总结
SM4,说白了就是咱们国标里的分组密码。密钥长度128位,分组长度也是128位,一共跑32轮迭代结构。最早是给无线局域网用的,后来成了GB/T 32907标准。我记得第一次在HSM里集成SM4时,还特意跟AES比过一轮——两者轮数差了快一倍,但SM4的硬件逻辑其实更紧凑。
算法全貌:别说你只知道AES
SM4用的是广义Feistel结构,但不是传统那种左右交换。它每轮只更新输出中的一个字,剩下的三个字直接移位。我个人习惯这样理解:你有一串四元组 (X₀, X₁, X₂, X₃),每轮算出一个新字,然后整个四元组右移一位。32轮下来四个字全换过了。
解密和加密共享同一套轮函数,只是轮密钥的顺序反过来。嗯,这里要留心:硬件复用的时候,密钥扩展器要能逆向输出轮密钥。
| 参数 | 值 |
|---|---|
| 密钥长度 | 128 bit |
| 分组长度 | 128 bit |
| 算法结构 | 广义Feistel(32轮) |
| 轮函数 | 非线性变换 T = S盒 + 线性L |
| 轮密钥数 | 32个(每个32 bit) |
加密流程:一步一步跟着走
拿一个128位明文进来,先拆成四个32位字:(X₀, X₁, X₂, X₃)。轮函数 F 长这样:
F(X₀, X₁, X₂, X₃, rk) = X₀ ⊕ T( X₁ ⊕ X₂ ⊕ X₃ ⊕ rk )
每一轮:
- 用
X₁, X₂, X₃和轮密钥rk异或 - 丢进 T变换,先过S盒再过L线性置换
- 和
X₀异或得到新字 - 输出
(X₁, X₂, X₃, 新字)
重复32轮后,最后一轮输出的四元组就是密文。我刚开始写SM4软件模拟时,总把更新顺序搞反,结果解密出来全是乱码。后来养了个习惯——画个轮序号表贴屏幕上,再也不出错了。
轮函数详解:S盒 + 线性L,缺一不可
T变换分两步:
- S盒替换:把32位拆成4个字节,每个字节查8×8 S盒(固定表,共256项)。S盒是SM4唯一非线性来源。
- 线性置换L:对S盒输出做一个32位的循环移位异或:
L(B) = B ⊕ (B ≪ 2) ⊕ (B ≪ 10) ⊕ (B ≪ 18) ⊕ (B ≪ 24)
移位方向全部左移。
你想想看,这个L其实就是个最大距离可分码的生成矩阵,扩散效果特别好。我在FPGA里直接把它写成多级XOR树,一个周期出结果。
uint32_t L(uint32_t B) {
return B ^ (B << 2) ^ (B << 10) ^ (B << 18) ^ (B << 24);
}
注意:移位后要 & 0xFFFFFFFF,但uint32_t自动溢出就行。
密钥扩展:别小看那32个轮密钥
密钥扩展用的几乎是同一套轮函数,区别只有两点:
- 输入的是系统密钥
MK₀~MK₃,先跟固定常数FK₀~FK₃异或得到初始状态K₀~K₃ - T变换里的L改成
L':移位循环位数不同
L'(B) = B ⊕ (B ≪ 13) ⊕ (B ≪ 23) - 每轮还加一个轮常数
CKᵢ(固定表)
流程:
Kᵢ₊₄ = Kᵢ ⊕ T'(Kᵢ₊₁ ⊕ Kᵢ₊₂ ⊕ Kᵢ₊₃ ⊕ CKᵢ)
rkᵢ = Kᵢ₊₄
嗯,这里的 T' 就是线性部分用L'替换。一共32个轮密钥,生成过程天然就是流水线友好的——你只需要保留最近4个K值不断滚动。
硬件实现要点:面积与速度的取舍
- S盒实现:128字节ROM,带1周期读延迟;如果追求高频,拆成4个BRAM并行读。
- 线性L:纯组合逻辑,无时序风险。
- 密钥扩展:可以和加密共享同一个S盒,但L'要单独实现。
- 抗侧信道:SM4对功耗/电磁攻击较敏感。我曾在一次安全审计中发现,不加掩码的S盒查表直接导致密钥泄露。建议至少做一阶布尔掩码。
| 维度 | SM4 | AES-128 |
|---|---|---|
| 轮数 | 32 | 10 |
| S盒规模 | 8×8 共256字节 | 8×8 共256字节 |
| 解密兼容 | 直接复用,密钥逆序 | 需独立逆S盒/逆列混合 |
| 典型面积(28nm) | ~8K GE | ~10K GE |
看到表格了吧?SM4面积占优,但32轮会拉长关键路径。解决方案是每轮做1时钟周期,32个周期完成分组。如果要求高吞吐,可以展开8轮流水,代价是面积翻倍。
图里画了整个数据流转:明文拆字后丢进32轮循环,每轮用轮函数和当前轮密钥更新X₀,然后四元组依次滚动。解密就是滚反向——从密文开始,用倒序的轮密钥走32轮,明文就回来了。
设计心得:算法越简单,陷阱越隐蔽
SM4的数学结构太对称了,导致硬件里随便一个时序错位都看不出来。我建议:
- 仿真时务必做“已知向量测试”,网上国密局发布的标准测试向量直接灌进去对。
- FPGA验证时加个计数器跑100万个随机分组,和软件参考结果逐字节比对。
- 如果做HSM,别忘了把S盒ROM的读写保护加上——侧信道攻击最喜欢偷查表时泄露的汉明重量。