{SM4.exe下载, https://lovexl-oss.oss-cn-beijing.aliyuncs.com/bed/SM4.exe, haofont hao-icon-book}

🗝️算法介绍

一、SM4概述

img

SM4是一种分组密码算法,其分组长度为128位(即16字节4字),密钥长度也为128位(即16字节4字)。其加解密过程采用了32轮迭代机制(与DES、AES类似),每一轮需要一个轮密钥(与DES、AES类似)。

二、加密过程

加密过程分为两步,由32次轮迭代1次反序变换组成。

步骤一:32次轮迭代

每一轮轮迭代都需要一个1字的轮密钥,总共需要32个轮密钥。迭代的过程就是不断地使用轮函数 F ,往后计算下一个字。

每一轮轮迭代都需要一个1字的轮密钥,总共需要32个轮密钥,记为 (rk_0,rk_1,\ldots,rk_{31})

轮函数 FF(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,\ldots,X_{32},X_{33},X_{34},X_{35})。到这里,我们就完成了加密过程的第一步。

步骤二:一次反序变换

加密过程的第二步是一次简单的反序变换。将迭代最后得到的四个字 (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的解密过程与加密过程完全相同,也包括32轮迭代和一次反序变换。只是在轮迭代的时候, 需要将轮密钥逆序使用。比如对 (rk_{31},rk_{30},\ldots,rk_1,rk_0) ,第一轮使用 rk_{31} ,第二轮使用rk_{30},以此类推。

四、轮函数F

轮函数内部需要执行的运算为

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

合成置换T接收1字的输入A,得出1字的输出C。它包含非线性变换 \tau线性变换 L 两个过程,即C=T(A)=L(\tau(A))

  1. 非线性变换通过对每个字节进行一个S盒代换实现。具体代换方法与AES中的字节代替相同。首先把一个字节的8位二进制写成2位十六进制,然后以十六进制的第一个数字为行,第二个数字为列,在S盒表中查找对应的数字。这样就可以把一个字节代替成另一个字节。例如 Sbox(EF)=84
  2. 线性变换公式:B=L(B)=B\oplus(B<<<2)\oplus(B<<<10)\oplus(B<<<18)\oplus(B<<<24).

五、密钥生成

解密时,轮密钥的生成方法与加密一致。

SM4的密钥为128位(4字),在32轮迭代中,每一轮都需要一个1字的轮密钥。

原始4字加密密钥为 MK=(MK_0,MK_1,MK_2,MK_3) (其中 MK_i 为1字) 。

步骤一:初始化密钥

首先需要让原始密钥的每个字 MK_i 与系统参数 FK_i 异或,得到4个新的字(K_{0},K_{1},K_{2},K_{3}) ,即(K_0,K_1,K_2,K_3)=

这里系统参数的取值为FK_0=(A3B1BAC6),FK_1=(56AA3350),FK_2=(677D9197),FK_3=(B27022DC)

步骤二:轮迭代生成轮密钥

  1. 迭代方法:

    与步骤四使用的轮函数基本一样

    例第一轮迭代为: 根据前面的4个字 (K_0,K_1,K_2,K_3) ,计算出第5个字 K_4 的值,并且将 K_{4} 作为第一轮的轮密钥 rk_0
    计算方法如下:rk_0=K_4=K_0\oplus T^{\prime}(K_1\oplus K_2\oplus K_3\oplus CK_0)(这里的T^{\prime} 类似于合成置换T ,CK_0 为固定参数,后边会讲T^{^{\prime}}CK_0 )

    往后与步骤四基本一样,CK0、CK1、、、都为固定参数。

    以此类推,一直进行32轮,直到得到32个轮密钥。这32个轮密钥就是密钥扩展算法的结果。

  2. 置换T^{\prime}

    与加密过程中的合成置换T 完全类似,也包括非线性变换和线性变换两部分。

    其中T^{^{\prime}}的非线性变换部分与T 完全相同。

    T^{^{\prime}}的线性变换与T 稍有区别,其线性变换 L^{^{\prime}}L^{\prime}(B)=B\bigoplus(B<<<13)\bigoplus(B<<<<23)

  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} 为第 iCK_i 的第 j 个字节,那么其构造方法为 ck_{i,j}=(4i+j)\times7(mod256)

    通过这样的计算方法,就可以得到32个CK_i ,从而运用到每一轮轮密钥的生成上去。


💣加密程序逆向

一、main函数分析

image-20240408224226119

如图所示,经过进入函数仔细比对算法,从宏观上我已经弄明白了该程序的两个关键函数:

  1. sm4_setkey:用来生成32个轮密钥。
  2. sm4_one_round:对明文进行32轮迭代加密+一次反序变换。

最后jmp将对密文按字节输出,这个在exe的运行结果上也是显而易见的,比较简单就不展开了。

二、sm4_setkey

该函数的主要功能步骤如下:

  1. 由于原始密钥是一字节一字节的存放在栈上

    image-20240408224926737

    所以第一步干的就是把他们化成完整的32位分组,具体步骤我标在了注释上👇

    image-20240408232144058 image-20240408232149727
  2. 第二步对应的算法中的密钥初始化,如下图

    image-20240408225314467

  3. 第三步也是关键步骤,进入循环,执行32次轮迭代,生成32个轮密钥

    image-20240408225601470

三、sm4CalciRK轮密钥的T’置换

我们进入sm4CalciRK函数,学习T‘置换的汇编表示

image-20240408232350480 image-20240408232400964

可以看到标志的信息,S核、左移13、23位,更加说明这是一个密钥的T'置换而不是T置换

四、sm4_one_round

该函数的主要功能为对明文进行32轮迭代加密以及一次反序变换

传入三个参数:

  1. var_30是用来存最终的密文的
  2. var_20放的是明文
  3. var_B0是生成的32个轮密钥

32轮迭代加密

32轮跟轮密钥的生成其实没有太大区别,所以这里的注释就相对简单了一点:

image-20240408230700229

轮函数F:

image-20240408230738304

加密明文的T置换:

image-20240408230804480

一次反序变换

image-20240408230828822