2. SM4算法数学基础:有限域、S盒与变换
聊SM4之前,得先把它的数学底子摸清楚。说实话,很多人学对称密码上来就背S盒、记轮函数,结果遇到密钥派生或者侧信道防护时一头雾水。我个人习惯是先把有限域、S盒构造、线性变换这三块啃透,后面看SM4的密钥编排和加解密流程就跟看流水线一样清楚。
2.1 有限域GF(2⁸)——SM4的“数字地基”
SM4所有操作都在GF(2⁸)上完成。什么叫GF(2⁸)?说白了就是一个只有256个元素的集合,每个元素可以用一个字节(8比特)表示。加法和乘法都在这个集合里封闭,不会跑出去。
加法:就是按位异或(XOR)。比如0x57 + 0x83 = 0xD4。你想想看,在GF(2⁸)里加法和减法是一回事,因为异或的逆操作还是异或。我在做密钥校验的时候经常利用这个性质——两次异或同一个数就能还原数据,调试起来特别方便。
乘法:稍微复杂点。它基于一个不可约多项式,SM4用的是x⁸ + x⁴ + x³ + x + 1(对应二进制1 0001 1011)。两个字节相乘,先做多项式乘法,再对这个不可约多项式取模。结果还是一个字节。
为什么非要用不可约多项式?
保证每个非零元素都有乘法逆元。没有逆元就没法做除法,S盒的仿射变换也就无从谈起。SM4选这个多项式,跟AES的0x11B只差一位,但SM4的S盒构造路径完全不同。
我的小技巧:实际工程里很少手算GF乘法。查表法最快——预计算256×256的乘法表,或者用对数/反对数表。我在嵌入式芯片上做过优化,用256字节的log表和alog表,乘法变成三次查表加一次加法,速度提升明显。
2.2 S盒构造原理——从代数到查表
SM4的S盒是8×8的,输入8比特,输出8比特。它由两步构成:
- 求乘法逆元:在GF(2⁸)里,把输入字节(0x00映射为自身)换成它的乘法逆元。
- 仿射变换:对逆元结果做一个仿射变换(矩阵乘法加常数)。
仿射变换的公式长这样:
b_i = a_i ⊕ a_{(i+2) mod 8} ⊕ a_{(i+5) mod 8} ⊕ a_{(i+7) mod 8} ⊕ c_i
其中 c = 0xD5 (二进制 1101 0101)
嗯,这里要注意:SM4的仿射常数是0xD5,而AES用的是0x63。别看就差这么点,整个S盒的代数性质全变了。我记得有一次做差分分析,把SM4的S盒跟AES的S盒对比,发现SM4的差分均匀度略高一点,但线性逼近的偏差更小——这是设计者有意做的权衡。
最终S盒的256个值可以直接查表。下面是SM4 S盒的前16个值(输入0x00~0x0F):
| 输入 | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B | 0x0C | 0x0D | 0x0E | 0x0F |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 输出 | 0xD6 | 0x90 | 0xE9 | 0xFE | 0xCC | 0xE1 | 0x3D | 0xB7 | 0x16 | 0xB6 | 0x14 | 0xC2 | 0x28 | 0xFB | 0x2C | 0x05 |
避坑指南:我曾经在移植SM4到DSP平台时,直接复制了AES的S盒代码,只改了常数。结果加解密结果全错。后来排查发现,SM4的仿射变换矩阵顺序跟AES不一样——SM4用的是行主序,AES是列主序。所以千万别偷懒,S盒必须按SM4标准重新生成。
2.3 线性变换与非线性变换——轮函数的“双引擎”
SM4的轮函数由非线性变换τ和线性变换L组成。τ就是S盒的并行应用,L是32比特的循环移位异或。
非线性变换τ:把32比特分成4个字节,每个字节过S盒。说白了就是4个S盒并行查表。这个操作提供了密码算法最核心的“混淆”能力——输入改变1比特,输出平均改变4比特。
线性变换L:对τ的输出做32比特的循环移位异或。SM4的加密轮函数用L,密钥编排用L'(略有不同)。
加密轮函数的L:
L(B) = B ⊕ (B <<< 2) ⊕ (B <<< 10) ⊕ (B <<< 18) ⊕ (B <<< 24)
密钥编排的L':
L'(B) = B ⊕ (B <<< 13) ⊕ (B <<< 23)
你想想看,为什么加密用5个移位项,密钥只用3个?因为密钥编排需要更快的扩散,但不需要跟加密轮一样的强度。我在做白盒SM4实现时,发现L的移位参数直接决定了查找表的大小——移位越多,表越大,但安全性也越高。
扩散效果对比:
- τ(S盒):1比特输入变化 → 约4比特输出变化(非线性)
- L(线性):1比特变化 → 经过一轮后影响约16比特(线性扩散)
- τ+L组合:一轮下来,32比特中约20比特会受影响
这就是为什么SM4只需要32轮就能达到充分扩散——比DES的16轮多一倍,但比AES的10轮(128位)效率更高。
2.4 知识体系总览
下面这张图把本章的核心逻辑串起来了。从最底层的有限域,到S盒构造,再到轮函数里的τ和L,最后到密钥编排——每一步都环环相扣。
这张图我建议你存下来。每次做SM4相关开发时扫一眼,就能快速定位问题出在哪一层——是S盒查表错了,还是L的移位参数配错了。我在做密钥分散算法时,就靠这张图排查出一个L'用成L的bug,省了大半天调试时间。