(六)国密SM4算法
SM4是一种分组密码算法,由我国国家密码管理局在2012年发布,常用于无线互联网加密等领域。
一、SM4概述
补充:密码算法中常用的一些数据单位:
位/比特/bit:指一个二进制位。
字节/byte: 1\ 字节=8\ 位
字/word: 1\ 字=4\ 字节=32\ 位
SM4是一种分组密码算法,其分组长度为128位(即16字节,4字),密钥长度也为128位(即16字节,4字)。其加解密过程采用了32轮迭代机制(与DES、AES类似),每一轮需要一个轮密钥(与DES、AES类似)。
二、SM4的加密过程
1、加密过程概述:
SM4的分组长度为4字,因此,其输入是4字的明文 (X_0,X_1,X_2,X_3) (其中 X_i 表示一个32位的字),经过加密后,得到的输出是4字的密文 (Y_0,Y_1,Y_2,Y_3) (其中 Y_i 表示一个32位的字)。
这个加密过程分为两步,由32次轮迭代和1次反序变换组成。
2、32次轮迭代:
首先,我们需要对这个4字明文进行32次轮迭代。每一轮轮迭代都需要一个1字的轮密钥,总共需要32个轮密钥,记为 (rk_0,rk_1,...,rk_{31}) (其中轮密钥 rk_i 在第 i-1 轮(这里从0开始算)迭代使用,长为1字)。之后会讲如何由原密钥得到32个轮密钥。
迭代的过程就是不断地使用轮函数 F ,往后计算下一个字。
这里插一句:轮函数 F 为 F(X_i,X_{i+1},X_{i+2},X_{i+3},rk_i) ,它可以接收4个1字的明文和1个1字的轮密钥作为参数,最终产生一个1字的结果。之后会详细讲轮函数的构造。
例如:我们现在给了4字明文 (X_0,X_1,X_2,X_3) ,第一轮迭代就是使用前4字明文和第一轮的轮密钥计算第5个字: X_4=F(X_0,X_1,X_2,X_3,rk_0) ,第二轮迭代就是计算第6个字: X_5=F(X_1,X_2,X_3,X_4,rk_1) ......,以此类推, X_{4+i}=F(X_i,X_{i+1},X_{i+2},X_{i+3},rk_i) (这里的 i\in[0,31] ,从0开始计数),执行32轮,最终,我们一共可以得到36个字 (X_0,X_1,X_2,X_3,...,X_{32},X_{33},X_{34},X_{35}) 。到这里,我们就完成了加密过程的第一步。
3、一次反序变换:
加密过程的第二步是一次简单的反序变换。将迭代最后得到的四个字 (X_{32},X_{33},X_{34},X_{35}) 进行反序,得到最终的密文 (Y_0,Y_1,Y_2,Y_3)=(X_{35},X_{34},X_{33},X_{32}) 。
这就是整个加密变换的过程。
三、SM4的解密过程
SM4的解密过程与加密过程完全相同,也包括32轮迭代和一次反序变换。只是在轮迭代的时候,需要将轮密钥逆序使用。比如对 (rk_{31},rk_{30},...,rk_1,rk_0) ,第一轮使用 rk_{31} ,第二轮使用 rk_{30} ,以此类推。
四、SM4轮函数 F 的构造
1、轮函数概述:
前文提到,轮函数 F(X_i,X_{i+1},X_{i+2},X_{i+3},rk_i) 接收5个1字的参数,前4个字 (X_i,X_{i+1},X_{i+2},X_{i+3}) 为明文字或者迭代中间值,最后一个参数为1字的轮密钥 rk_i 。轮函数的输出结果为1字。
轮函数内部需要执行的运算为 F(X_i,X_{i+1},X_{i+2},X_{i+3},rk_i)=X_i\oplus T(X_{i+1}\oplus X_{i+2}\oplus X_{i+3}\oplus rk_i)
公式后边的 T 为合成置换。
2、合成置换 T :
合成置换 T 接收1字的输入 A ,得出1字的输出 C 。它包含非线性变换 \tau 和线性变换 L 两个过程,即 C=T(A)=L(\tau(A))
(1)非线性变换 \tau :
非线性变换接收1字(即4个字节)的输入,记为 A=(a_0,a_1,a_2,a_3) (其中 a_i 为一个字节),输出1字的结果,记为 B=(b_0,b_1,b_2,b_3) 。
非线性变换就是对输入参数的每个字节进行S盒(Sbox)变换,得到输出结果,即
B=(b_0,b_1,b_2,b_3)=\tau (A) =(Sbox(a_0),Sbox(a_1),Sbox(a_2),Sbox(a_3))
S盒如下图所示:
具体代换方法与AES中的字节代替相同。首先把一个字节的8位二进制写成2位十六进制,然后以十六进制的第一个数字为行,第二个数字为列,在S盒表中查找对应的数字。这样就可以把一个字节代替成另一个字节。例如 Sbox(EF)=84
(2)线性变换 L :
补充:
循环左移的概念:在密码学中,常对一个数据进行循环左移。具体做法就是,把数据向左移动若干位,左边溢出的数字补到右边。例如:对1234567左移三位,得到4567123。
我们使用 <<< 符号来表示对一个循环左移,例如 B<<<3 表示对 B 循环左移3位。
线性变换接收1字的 B 作为输入,经过运算,得出1字的输出 C 。
运算公式如下:
B=L(B)= B\oplus(B<<<2)\oplus (B<<<10)\oplus(B<<<18)\oplus(B<<<24) .
经过非线性变换和线性变换,就完成了一次轮迭代,计算出了下一个字的内容。
五、SM4的密钥扩展算法
前文提到,SM4的密钥为128位(4字)。然而,在32轮迭代中,每一轮都需要一个1字的轮密钥。如何由4字的原始密钥获得32个1字的轮密钥?这个问题就要靠密钥扩展算法来解决。
原始4字加密密钥为 MK=(MK_0,MK_1,MK_2,MK_3) (其中 MK_i 为1字)。
1、与系统参数异或——初始化密钥:
首先需要让原始密钥的每个字 MK_i 与系统参数 FK_i 异或,得到4个新的字 (K_0,K_1,K_2,K_3) ,即 (K_0,K_1,K_2,K_3)= (MK_0\oplus FK_0,MK_1\oplus FK_1,MK_2\oplus FK_2,MK_3\oplus FK_3) .
这里系统参数的取值为
2、轮迭代生成轮密钥:
(1)迭代方法:
在对密钥进行初始化后,我们得到了4个新的字 (K_0,K_1,K_2,K_3) 。
之后,与加密过程类似,需要对这四个字进行32轮迭代,生成32个轮密钥。
第一轮迭代为:
根据前面的4个字 (K_0,K_1,K_2,K_3) ,计算出第5个字 K_4 的值,并且将 K_4 作为第一轮的轮密钥 rk_0 ,计算方法如下:
rk_0=K_4=K_0\oplus T^{'}(K_1\oplus K_2\oplus K_3\oplus CK_0) .(这里的 T^{'} 类似于合成置换 T , CK_0 为固定参数,后边会讲 T^{'} 和 CK_0 )
第二轮迭代为:
根据 (K_1,K_2,K_3,K_4) ,计算出第6个字 K_5 的值,并且将 K_5 作为第二轮的轮密钥 rk_1 ,计算方法如下:
rk_1=K_5=K_1\oplus T^{'}(K_2\oplus K_3\oplus K_4\oplus CK_1) .
以此类推,一直进行32轮,直到得到32个轮密钥。这32个轮密钥就是密钥扩展算法的结果。
其通式为:
(2)置换 T^{'} :
密钥扩展算法中的 T^{'} 与加密过程中的合成置换 T 完全类似,也包括非线性变换和线性变换两部分。其中 T^{'} 的非线性变换部分与 T 完全相同。 T^{'} 的线性变换与 T 稍有区别,其线性变换 L^{'} 如下:
(3)固定参数 CK_i 的取值:
一共有32个 CK_i i\in[0,31] ,即计算每一轮的轮密钥时,均需要使用不同的 CK_i 。
CK_i 长为1字,可以表示为4个字节 CK_i=(ck_{i,0},ck_{i,1},ck_{i,2},ck_{i,3}) .
假设 ck_{i,j} 为第 i 个 CK_i 的第 j 个字节,那么其构造方法为 ck_{i,j}=(4i+j)\times7(mod\ 256) 。
通过这样的计算方法,就可以得到32个 CK_i ,从而运用到每一轮轮密钥的生成上去。
附:
32个 CK_ii\in[0,31] 的具体值为:
解密时,轮密钥的生成方法与加密一致。
附:
SM4算法总结图示:
参考资料:
《GBT 32907-2016 信息安全技术 SM4分组密码算法》