3. SM4分组密码算法原理

SM4是我国商用密码体系中用于对称加密的分组密码算法,最早以无线局域网分组密码标准的形式发布,后成为国家标准GB/T 32907—2016《信息安全技术 SM4分组密码算法》。它采用分组长度128比特、密钥长度128比特、32轮迭代的Feistel型结构,加解密共用同一套轮函数,仅轮密钥使用顺序相反。理解SM4的关键在于四件事:整体结构如何组织、轮函数如何运算、轮密钥如何从主密钥扩展、S盒如何提供非线性,以及这些设计如何共同支撑安全性。

一、整体结构与数据表示

SM4把128比特明文按字节顺序划分为4个32比特字,记为X0、X1、X2、X3。每一轮只更新其中一个字,其余三个字直接移位保留,这是典型的不平衡Feistel结构。设第i轮输入为(Xi, Xi+1, Xi+2, Xi+3),则轮函数输出为:

X[i+4] = X[i] XOR T( X[i+1] XOR X[i+2] XOR X[i+3] XOR rk[i] )

其中rk[i]为第i轮32比特轮密钥,T为合成置换。经过32轮后得到(X32, X33, X34, X35),再经反序变换R输出密文:

C = R(X32, X33, X34, X35) = (X35, X34, X33, X32)

反序变换是SM4的一个显著特征。它使得解密过程可以完全复用加密的轮函数,只需把轮密钥逆序使用,即解密时第i轮使用rk[31−i]。这种“加密解密同构”的设计降低了硬件实现面积,也简化了软件实现中的代码复用。

二、轮函数与合成置换T

轮函数的核心是合成置换T,它由非线性变换τ和线性变换L复合而成,即T(·)=L(τ(·))。τ对32比特输入按字节并行处理,每个字节通过同一个8比特S盒映射为另一个字节,因此τ是一个32比特到32比特的非线性双射。L则是一个线性变换,对τ的输出B进行循环移位与异或:

L(B) = B XOR (B <<< 2) XOR (B <<< 10) XOR (B <<< 18) XOR (B <<< 24)

这里的“<<<”表示32比特循环左移。线性变换的作用是把S盒产生的局部非线性扩散到整个32比特字中,使单个字节的变化在若干轮后影响全部比特。非线性变换τ提供混淆,线性变换L提供扩散,两者结合构成SM4轮函数的安全基础。

三、密钥扩展算法

SM4的密钥扩展与加密结构高度相似,同样使用32轮迭代,但轮函数中的线性变换改为L′:

L'(B) = B XOR (B <<< 13) XOR (B <<< 23)

设主密钥MK=(MK0, MK1, MK2, MK3),首先与系统参数FK异或得到K0至K3:

K[i] = MK[i] XOR FK[i],  i = 0,1,2,3

然后对i=0到31计算:

rk[i] = K[i+4] = K[i] XOR T'( K[i+1] XOR K[i+2] XOR K[i+3] XOR CK[i] )

其中T′(·)=L′(τ(·)),CK[i]为固定常数。FK和CK都是标准中规定的固定值,用于消除全零密钥等弱密钥风险,并保证密钥扩展具有良好的雪崩效应。密钥扩展的输出是32个32比特轮密钥,共1024比特,远大于原始128比特主密钥,但每个轮密钥都由主密钥经非线性迭代导出,不能由单个轮密钥反推主密钥。

SM4 加密与解密流程(32轮 Feistel 结构) 加密 明文 X0 X1 X2 X3(128 bit) 轮函数 F:X[i+4] = X[i] ⊕ T(X[i+1]⊕X[i+2]⊕X[i+3]⊕rk[i]) T = L(τ(·)),τ 为 S 盒字节代换,L 为循环移位异或 重复 32 轮,轮密钥 rk[0] → rk[31] 反序变换 R:C = (X35, X34, X33, X32) 密文(128 bit) 解密 密文 X0 X1 X2 X3(128 bit) 同一轮函数 F,轮密钥逆序使用 第 i 轮使用 rk[31 − i] 重复 32 轮,rk[31] → rk[0] 反序变换 R 明文(128 bit) 密钥扩展 MK → K0..K3 rk[i]=K[i]⊕T′(…⊕CK[i]) 输出 rk[0..31] S 盒与线性变换 τ:8 bit S 盒并行代换(非线性) L:B⊕(B<<<2)⊕(B<<<10)⊕(B<<<18)⊕(B<<<24) L′:B⊕(B<<<13)⊕(B<<<23)(密钥扩展) 安全性要点 32 轮迭代,差分/线性攻击复杂度 ≥ 2^126 S 盒满足双射、非线性度、差分均匀性 密钥扩展与加密结构同构,抗相关密钥攻击

四、S盒设计

SM4的S盒是一个8比特输入、8比特输出的固定置换表,共256项。它并非随机生成,而是基于有限域GF(28)上的求逆运算与仿射变换构造,与AES的S盒在数学结构上有相似之处,但具体参数不同。S盒的设计需要同时满足多项密码学指标:双射性保证可逆;非线性度足够高以抵抗线性密码分析;差分均匀性足够低以抵抗差分密码分析;此外还要避免存在明显的代数结构或固定点。SM4的S盒经过公开评估,其差分均匀性、线性偏差等指标均达到分组密码设计的常规安全要求。

在实现层面,S盒通常以查找表形式存在。软件实现时,一个32比特字经过τ变换,等价于把该字拆成4个字节分别查表再拼回。硬件实现则可以用组合逻辑或ROM实现。需要注意的是,S盒查表可能带来缓存时序侧信道风险,在高安全场景中需要采用位切片、掩码或恒定时间查表等防护手段。

五、加解密流程与正确性

加密流程可以概括为:明文经初始分组后进入32轮迭代,每轮用当前轮密钥rk[i]参与运算,最后一轮结束后做反序变换得到密文。解密流程与加密完全一致,唯一区别是轮密钥使用顺序相反。这种对称性来自Feistel结构本身的性质:轮函数不需要可逆,只要轮密钥顺序正确,解密就能还原明文。

下面给出一个简化的软件实现骨架,用于说明轮函数与密钥扩展的调用关系:

// 加密:输入 X[0..3],输出 Y[0..3]
for (i = 0; i < 32; i++) {
    X[i+4] = X[i] ^ T(X[i+1] ^ X[i+2] ^ X[i+3] ^ rk[i]);
}
Y = { X[35], X[34], X[33], X[32] };

// 解密:输入 Y[0..3],输出 X[0..3]
for (i = 0; i < 32; i++) {
    Y[i+4] = Y[i] ^ T(Y[i+1] ^ Y[i+2] ^ Y[i+3] ^ rk[31 - i]);
}
X = { Y[35], Y[34], Y[33], Y[32] };

验证加解密正确性时,可以用标准测试向量:主密钥与明文均为全零时,SM4加密结果应为标准中给出的固定密文。实际工程中,建议至少覆盖全零、全一、单比特翻转、随机向量等用例,并检查加密后再解密能否还原原始明文。

六、安全性分析

SM4的安全性建立在32轮迭代、非线性S盒、线性扩散层和密钥扩展的联合作用之上。从差分分析角度看,S盒的低差分均匀性使单轮差分特征概率很低,32轮后有效差分特征的概率通常低于2−126,不足以支撑实用攻击。从线性分析角度看,S盒的非线性度使线性逼近偏差很小,同样需要超过2126量级的数据量才能形成有效区分器。密钥扩展采用与加密同构的迭代结构,轮密钥之间高度非线性相关,能够抵抗相关密钥攻击和滑动攻击。

需要强调的是,算法本身安全不等于系统安全。SM4在实际使用中必须配合正确的分组密码工作模式,如CBC、CTR、GCM等,并配合安全的密钥管理、随机数生成和消息认证机制。若直接使用ECB模式加密结构化数据,即使SM4算法本身没有弱点,也会因模式缺陷导致信息泄露。此外,侧信道防护、密钥生命周期管理、协议层抗重放设计等,都是SM4工程应用中不可忽略的安全环节。

SM4的加解密共用轮函数,实现时只需一份轮函数代码,通过轮密钥顺序切换即可完成加密与解密,这是它在嵌入式与硬件实现中广受欢迎的重要原因。
S盒查表实现可能引入缓存时序侧信道。在安全芯片、移动支付、车联网等场景中,应优先采用恒定时间实现或掩码防护,避免直接使用普通内存查表。