本文主要是介绍SM4分组密码算法研究,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
SM4算法详解
分组密码将明文数据按固定长度进行分组,并在同一密钥控制下逐组进行加密,从而将各个明文分组变换成一个个等长的密文分组。
分组密码的设计一般基于混淆原则和扩散原则。
混淆原则指的是将密文、明文、密钥三者之间的统计关系和代数关系变得尽可能复杂,使敌手即使获得了密文和明文,也无法求出密钥的任何信息,即使获得了密文和明文的统计规律,也无法求出明文的任何信息。
扩散原则是将明文的统计规律和结构规律散射到相当长的一段统计中去。即,明文中的每一位会影响密文中的尽可能多的位,或者说让密文中的每一位都受到明文中的尽可能多位的影响。
分组密码主要的应用场景,包括无需进行密钥交换;防止明文传输过程被窃取;数据量大,加解密速度要求快等场景。
SM4算法流程
SM4算法主要包括异或、移位以及盒变换操作。其中密钥拓展和加/解密为两个主要模块,其流程大同小异。
其中,移位变换是指循环左移;盒变换将8bit输入映射到8bit输出的变换,是一个固定的变换。
下图1给出了 SM4算法的加解密(左)和密钥拓展(右)的流程图。
(1)加/解密模块
加/解密算法由32次迭代运算和1次反序变换组成,具体步骤如下所述。
设,明文输入为 ( X 0 , X 1 , X 2 , X 3 ) (X_0, X_1, X_2, X_3) (X0,X1,X2,X3), X i X_i Xi为32 比特的数据,密文输出为 ( Y 0 , Y 1 , Y 2 , Y 3 ) (Y_0, Y_1, Y_2, Y_3) (Y0,Y1,Y2,Y3),轮密钥为 r k i rk_i rki。
① 当 i = 0 i=0 i=0 时为第一次轮变换,一直进行到 i = 31 i=31 i=31 结束。
②将 X i + 1 , X i + 2 , X i + 3 X_{i+1} , X_{i+2} , X_{i+3} Xi+1,Xi+2,Xi+3 和轮密钥 r k i rk_i rki 异或得到一个 32 32 32 比特的数据,作为盒变换的输入。即, s b o x i n p u t = X i + 1 ⊕ X i + 2 ⊕ X i + 3 ⊕ r k i sbox_{input} = X_{i+1} ⊕ X_{i+2} ⊕ X_{i+3}⊕rk_i sboxinput=Xi+1⊕Xi+2⊕Xi+3⊕rki, ⊕ ⊕ ⊕ 符号代表异或运算。
③ 将 s b o x i n p u t sbox_{input} sboxinput 拆分成 4 4 4个 8 8 8比特数据,分别进行盒变换,之后再将 4 4 4个 8 8 8比特输出合并成一个 32 32 32 比特的 s b o x o u t p u t sbox_{output} sboxoutput。
④ 将上一步获得的 s b o x o u t p u t sbox_{output} sboxoutput分别循环左移 2,10,18,24 位,得到 4个 32比特的结果,记移位结果为 y 2 , y 10 , y 18 , y 24 y2,y10,y18,y24 y2,y10,y18,y24。与盒变换输出 s b o x o u t p u t sbox_{output} sboxoutput 和 X i X_i Xi 异或,得到 X i + 4 X_{i+4} Xi+4。即, X i + 4 = s b o x o u t p u t ⊕ y 2 ⊕ y 10 ⊕ y 18 ⊕ y 24 ⊕ X i X_{i+4}=sbox_{output}⊕y2⊕y10⊕y18⊕y24⊕X_i Xi+4=sboxoutput⊕y2⊕y10⊕y18⊕y24⊕Xi。
至此完成了一轮的加/解密运算。
⑤将最后一轮生成的 4 4 4个 32 32 32比特数据 X 35 X_{35} X35, X 34 X_{34} X34, X 33 X_{33} X33, X 32 X_{32} X32 合并成一个 128 b i t 128 \ bit 128 bit 的数据输出,作为最后的密文 ( Y 0 , Y 1 , Y 2 , Y 3 ) (Y_0, Y_1, Y_2, Y_3) (Y0,Y1,Y2,Y3)输出。
(2) 密钥扩展模块
密钥扩展与加/解密实现过程大同小异,具体实现过程如下所述。
设,密钥输入为 ( M K 0 , M K 1 , M K 2 , M K 3 ) (MK_0, MK_1, MK_2, MK_3) (MK0,MK1,MK2,MK3),轮密钥输出为 K i , i ∈ { 0 , 1 , 2 , … 31 } K_i, i∈\{0,1,2,…31\} Ki,i∈{0,1,2,…31}。
① 将初始密钥 ( M K 0 , M K 1 , M K 2 , M K 3 ) (MK_0, MK_1, MK_2, MK_3) (MK0,MK1,MK2,MK3)分别异或固定参数 ( F K 0 , F K 1 , F K 2 , F K 3 ) (FK_0, FK_1, FK_2, FK_3) (FK0,FK1,FK2,FK3)得到用于循环的密钥 ( K 0 , K 1 , K 2 , K 3 ) (K_0, K_1, K_2, K_3) (K0,K1,K2,K3),即, K 0 = M K 0 ⨁ F K 0 K_0= MK_0⨁FK_0 K0=MK0⨁FK0, K 1 = M K 1 ⨁ F K 1 K_1=MK_1⨁FK_1 K1=MK1⨁FK1, K 2 = M K 2 ⨁ F K 2 K_2=MK_2⨁FK_2 K2=MK2⨁FK2, K 3 = M K 3 ⨁ F K 3 K_3=MK_3⨁FK_3 K3=MK3⨁FK3 。
② 进入轮密钥 K i K_i Ki 的生成, 当 i = 0 i=0 i=0 时为第一轮密钥扩展,一直进行到 i=31 结束。
③ 将 K i + 1 , K i + 2 , K i + 3 K_{i+1}, K_{i+2}, K_{i+3} Ki+1,Ki+2,Ki+3 和固定参数 C K i CK_i CKi异或得到一个 32 32 32 比特的数据,作为盒变换的输入。即, s b o x i n p u t = K i + 1 ⊕ K i + 2 ⊕ K i + 3 ⊕ C K i sbox_{input}=K_{i+1}⊕K_{i+2}⊕K_{i+3}⊕CK_i sboxinput=Ki+1⊕Ki+2⊕Ki+3⊕CKi。
④ 将 s b o x i n p u t sbox_{input} sboxinput 拆分成 4 4 4 个 8 8 8 比特数据,分别进行盒变换,之后再将 4 4 4 个 8 8 8比特输出合并成一个 32 32 32 比特的 s b o x o u t p u t sbox_{output} sboxoutput。
⑤ 将上一步获得的 s b o x o u t p u t sbox_{output} sboxoutput分别循环左移 13 13 13, 23 23 23 位,得到 2 2 2个 32 32 32 比特的结果,记移位结果为 y 13 y13 y13, y 23 y23 y23与盒变换输出 s b o x o u t p u t sbox_{output} sboxoutput 和 K i K_i Ki 异或,得到 K i + 4 K_{i+4} Ki+4。即, K i + 4 = s b o x o u t p u t ⊕ y 13 ⊕ y 23 ⊕ K i K_{i+4} =sbox_{output}⊕y13⊕y23⊕K_i Ki+4=sboxoutput⊕y13⊕y23⊕Ki。
其中每一个 K i K_i Ki即为产生的轮密钥。
具体算法实现
SM4算法的主体代码包括加解密模块和密钥扩展模块。以下为加解密模块具体实现代码以及注释。
(1)加/解密模块
def _do(self, text: bytes, key_r: list):text_ = [0 for _ in range(4)]# 将 128bit 转化成 4x32bitfor i in range(4):text_[i] = int.from_bytes(text[4 * i:4 * i + 4], 'big')for i in range(32):box_in = text_[1] ^ text_[2] ^ text_[3] ^ key_r[i]box_out = self._s_box(box_in)temp = text_[0] ^ box_out ^ self._rot_left(box_out, 2) ^ self._rot_left(box_out,10)temp = temp ^ self._rot_left(box_out, 18) ^ self._rot_left(box_out, 24)text_ = text_[1:] + [temp]text_ = text_[::-1] # 结果逆序# 将 4x32bit 合并成 128bitresult = bytearray()for i in range(4):result.extend(text_[i].to_bytes(4, 'big'))return bytes(result)
(2)密钥扩展模块
def _generate_key(self, key: bytes):"""密钥生成"""key_r, key_temp = [0 for _ in range(32)], [0 for _ in range(4)]FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]CK = [0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279]# 将 128bit 拆分成 4x32bitfor i in range(4):temp = int.from_bytes(key[4 * i:4 * i + 4], 'big')key_temp[i] = temp ^ FK[i]# 循环生成轮密钥for i in range(32):box_in = key_temp[1] ^ key_temp[2] ^ key_temp[3] ^ CK[i]box_out = self._s_box(box_in)key_r[i] = key_temp[0] ^ box_out ^ self._rot_left(box_out, 13) ^ self._rot_left(box_out, 23)key_temp = key_temp[1:] + [key_r[i]]return key_r
SM4算法性能及可靠性分析
分组密码算法最主要的是要保证传输信息的机密性以及完整性,才能保证信息在传输过程中不被敌手窥探到。其次,随着大数据的到来,越来越多的信息在网上传播,因此算法的性能,即,执行效率显得尤为重要。与国际主流分组密码算法进行比较,可得出表1的结果。
表1. SM4与DES和AES算法比较
项目 | DES | AES | SM4 |
---|---|---|---|
算法结构 | 平衡Feistel | Substitution-Permutation | 非平衡Feistel |
计算轮数 | 16轮 | 10/12/14轮 | 32轮 |
分组长度 | 64 | 128 | 128 |
密钥长度 | 64 | 128/192/256 | 128 |
加解密过程 | 相同 | 不同 | 相同 |
算法复杂性分析
以下可以与主流国际分组密码算法DES和算法AES在空间和时间复杂度上来进行分析,比较其三种主要分组密码算法的复杂性。
(1) 空间复杂度
DES算法需要存储 2 2 2个IP置换矩阵, 2 × 16 × 4 2×16×4 2×16×4;扩展置换, 6 × 8 6×8 6×8;S盒代换, 16 × 4 × 8 16×4×8 16×4×8;置换选择 P C 1 PC1 PC1, 7 × 8 7×8 7×8;置换选择 P C 2 PC2 PC2, 8 × 6 8×6 8×6。
SM4算法需要存储S盒,大小为 2 4 × 2 4 2^4×2^4 24×24。
AES算法需要存储 2 2 2个S盒,大小为 2 × 2 4 × 2 4 2×2^4×2^4 2×24×24。
其他代码运行过程中存储的变量可忽略不计,从以上比较来看,SM4分组密码算法所需的内存空间最少,AES次之,DES则最多。
(2) 时间复杂度
时间复杂度可以简单从计算轮数进行简单的比较,AES的计算轮数最少为 10 / 12 / 14 10/12/14 10/12/14,DES次之,为 16 16 16轮,SM4算法计算轮数最多,达 32 32 32轮。
(3) 代码运行结果比较
采用Python语言,实现三种分组密码算法(具体代码参见 python实现)。并分别使用其进行一次加密运算,比较各自运行时所占用的内存大小以及运行时间。结果如下表2所示。
表2. 占用的内存大小以及运行时间
项目 | 内存占用 | 运行时间 |
---|---|---|
DES | 24576B | 365 m s 365ms 365ms |
AES | 20480B | 386 m s 386ms 386ms |
SM4 | 28672B | 341 m s 341ms 341ms |
从表2中的运行结果来看,SM4算法运行时需要占用更多的内存,运行时间上则更快。与理论上分析的结果不一致。
安全性分析
首先,从密钥空间上考虑,密钥空间越大,敌手可通过穷举的方法爆破密钥的可能性就越低。DES的密钥长度为64bits,AES的密钥长度为 128 / 192 / 256 b i t s 128/192/256\ bits 128/192/256 bits,SM4的密钥长度为 128 b i t s 128\ bits 128 bits。其中密钥长度越长,则代表密钥空间越大。AES最安全,SM4次之,最后是DES。其次,从算法特性上分析,SM4和AES均包含非线性变化,得到的密文统计特性更差,则更安全。最后,从攻击的角度分析,如,差分密码分析、线性密码分析、不可能差分分析等等,公开的评估结果表明,SM4分组密码能够抵抗目前已知的所有攻击。
参考文献
[1] 吕述望等. “SM4分组密码算法综述.” 信息安全研究 2.11(2016):13.
[2] 胡景秀等. “国密算法分析与软件性能研究.” 信息网络安全 10(2021):9.
资源下载
包括完整的AES、DES以及DES分组密码算法的python代码实现。
python代码实现
这篇关于SM4分组密码算法研究的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!