一种基 于非线性双射的SM4白盒实现
本文档主要介绍基于非线性双射的SM4白盒实现方案,包括设计原理、代码实现的详细流程、安全性分析、与现有SM4白盒实现的比较以及白盒API调用示例。
1 设计原理
本方案采用了非线性双射置乱编码技术,用于对SM4算法中的查找表进行有效地混淆和保护。与传统的线性仿射变换[1]相比,非线性双射的设计显著提高了查找表的安全性,这种设计避免了在白盒实现中常见的、攻击者可能利用的数学特征,从而使得查找表能够成功抵御那些专门针对白盒实现的攻击。此外,本方案还对SM4算法的每一轮加解密计算过程进行了细致的拆分,将其分为个若干独立的部分,这一拆分过程遵循了如图1-1所示的构造方法,通过精心设计的置乱编码生成查找表,每一部分都应用了经过特别设计的置乱编码技术,以实现对查找表的混淆。这种混淆机制有效地隐藏了密钥信息,从而在白盒攻击环境下确保了SM4算法的加解密过程的安全性。
图1-1 非线性双射白盒SM4方案架构图
方案具体实现如图1-1所示。其中,表示四个并行的8位随机非线性双射,表示四个并行的8位随机仿射变换,而和除了所对应的常数项中所有元素的值均被置为0之外,变换和完全一致,变换和完全一致。这里所提到的仿射变换可以与有限域上的矩阵运算等效,上述四个变换的设计原理在于,对于仿射变换,其变换结果在互相进行按位异或操作后,常数部分会被抵消,即在中满足式(1):
在图1-1中,函数如式(2)所示,其中表示加密轮次。是轮密钥的组成部分,,如式(3)所示:
线性变换可以表示为与一个上的32×32位的矩阵相乘,该矩阵的定义如式(4)所示,其组成元素是由1和0组成的矩阵。
基于每一轮SM4算法的计算过程,图1-1中每一部分所实现的功能如下:Part 1和Part 4-1实现三者的按位异或运算;Part 2和Part 4-2实现该计算结果与轮密钥的按位异或运算,再将结果进行变换操作;最后,Part 3和Part 4-3实现上述变换的结果与的按位异或计算。
在本方案中,我们将前述的运算过程以查找表的形式进行表示,并将这些查找表存储于本地设备上,需要特别指出的是,此处仅保存了每一部分运算中经过一系列变换复合 后得到的最终变换所对应的查找表。如果为每个单独的变换都创建并存储其对应的查找表,那么置乱编码的关键信息将有可能被直接暴露,从而无法确保白盒实现方法的安全性。为了确保查找表能够准确反映每一部分的输入与输出之间的关系,对于每个可能的输入值,都必须存储其相应的输出值,因此,为了防止查找表的体积过大,我们不能为输入数据分配过多的位数。同时,为了确保查找表具有足够的混淆效果,输入数据的位数也不能设置得过少,在SM4算法中,每一轮的输入数据被划分为4个区块,每个区块包含32位,经过编码处理后,每个区块的长度仍然保持为32位。考虑到避免查找表占用过多内存,本实现方案将每一部分的输入数据以8位为单位进行细分。因此,上文中提到的混淆操作全部是基于四个并行的8位变换来实现的。对于Part 1、Part 2和Part 3,每张查找表的输入数据长度为8位,这意味着需要存储条数据。而对于Part 4-1、Part 4-2和Part 4-3,由于需要实现包含编码和解码操作的按位异或功能,每张查找表的输入数据长度为16位,因此需 要存储条数据。通过这种设计,我们能够在保证查找表具有足够混淆效果的同时,有效控制查找表的体积,从而在白盒环境下实现SM4算法的安全运算。
显然,Part 4-1、 Part 4-2 和 Part 4-3 中的查找表占据了大部分的存储空间。因此本方案对有关查找表的编码与解码函数进行设计,使得 Part 4-1与 Part 4-2的查找表能够重复利用,从而降低了对存储空间的需求。如图1-1所示,对 Part 4-1和Part 4-2,其中一个输入的解码函数,即和,与输出的编码函数,即和相匹配。为了进一步提升查找表的多样性和含混度,在输出编码时分别引入仿射变换和,可以在不影响查找表功能,同时不增加内存占用的前提下,有效提升其安全性。由于仿射变换的引入,其他部分的查找表也需要增加相应的混淆函数,具体的添加方式如图1-1所示。通过以上的设计,部分查找表可实现 复用,进而使得所需要的总存储空间减少了大约一半。大部分设备的内存空间足够用来存储本实现方法,可以保证本方案在大多数情况下的实用性。
2 代码实现的详细流程
基于非线性双射的白盒SM4实现代码包括查找表生成与加密算法实现两部分,加解密流程如图2-1所示。代码主要参考了Xiao-Lai白盒SM4实现[2]和Bai-Wu白盒SM4实现[3]和 Xiao-Lai白盒AES实现[4]。本文对应的代码实现链接为nonlinearwbsm4。
图2-1 非线性双射白盒SM4加解密流程
2.1 查找表生成
1)初始化
- 定义 SM4 算法相关常量,如 S 盒、轮密钥生成所需的 FK 和 CK 常量。
- 声明一系列非线性和仿射变换的变量,用于后续表的生成。
- 调用
wbsm4_gen_init
函数,生成 36 轮的Pij
和Pij_inv
非线性 双射对,并将其组合成 32 位的Pi
和Pi_inv
。同时,生成 32 轮的Ei
、Fi
、Gi
、Ai
、Qi
、Hi
、Bi
、Wi
、Ci
、Di
及其逆变换,每个 32 位变换由 4 个 8 位变换组成。
2) 各部分查找表生成
wbsm4_gen_part1
:生成 32 轮的查找表part1_table1
、part1_table2
和part1_table3
,每轮有 4 个输入 8 位、输出 8 位的查找表。通过对Pij_inv
与Eij_inv
、Fij_inv
、Gij
进行复合运算得到。wbsm4_gen_part2
:依赖于 SM4 轮密钥sm4_key
,生成查找表part2_table_temp
和part2_table
。part2_table_temp
通过对Eij
、Gij_inv
、Aij_inv
进行复合运算,并与轮密钥异或后查 S 盒得到;part2_table
则是对不同移位的输入进行Qi
、Wi
、Hi
变换得到。wbsm4_gen_part3
:生成查找表part3_table1
、part3_table1_dec
和part3_table2
。part3_table1
和part3_table1_dec
通过对Pij_inv
与Cij
进行复合运算得到;part3_table2
通过对Qij_inv
、Hij_inv
、Bij_inv
进行复合运算,并经过Dij
变换得到。wbsm4_gen_part4_1
:生成 32 轮的查找表part4_1_table
,每轮有 4 个输入 16 位、输出 8 位的查找表。通过对Eij
和Fij
进行异或,再经过Gij
和Eij_inv
变换得到。wbsm4_gen_part4_2
:生成 32 轮的查找表part4_2_table
,每轮有 4 个输入 16 位、输出 8 位的查找表。通过对Qij_inv
和Wij_inv
进行异或,再经过Hi
和Qi
变换得到。wbsm4_gen_part4_3
:生成 32 轮的查找表part4_3_table
和part4_3_table_dec
,每轮有 4 个输入 16 位、输出 8 位的查找表。通过对Cij_inv
和Dij_inv
进行异或,再经过Pij
变换得到。
查找表生成的函数接口如下:
void Nonlinearwbsm4_generate_tables(const uint8_t key[16], WB_SM4_Tables* tables);
2.2 加密函数的实现
1)输入外部编码
- 把 16 字节的输入数据
IN
拆分成 4 个 32 位的整数x0
、x1
、x2
、x3
。 - 分别对
x0
、x1
、x2
、x3
运用tables->P[0]
、tables->P[1]
、tables->P[2]
、tables->P[3]
进行非线性变换。
2)执行核心加密
进行 32 轮迭代,每轮迭代包含以下步骤:
- part1:借助查找表
part1_table1
、part1_table2
、part1_table3
对x1
、x2
、x3
进行变换,得到xt1
、xt2
、xt3
。 - part4-1:把
xt1
、xt2
、xt3
按 8 位分割,利用查找表part4_1_table
进行变换,得出x4
。 - part2:将
x4
按 8 位分割,使用查找表part2_table_temp
进行变换,再通过矩阵乘法MatMulNumM32
对结果进行处理,接着利用查找表part2_table
进一步变换,得到中间结果。 - part4-2:把中间结果按 8 位分割,利用查找表
part4_2_table
进行变换,更新x4
。 - part3:借助查找表
part3_table1
、part3_table2
对x0
、x4
进行变换,得到xt0
、xt4
。 - part4-3:把
xt0
、xt4
按 8 位分割,利用查找表part4_3_table
进行变换,更新x4
。 - 更新
x0
、x1
、x2
、x3
的值,即x0 = x1; x1 = x2; x2 = x3; x3 = x4;
。
3)输出外部解码
- 分别对
x3
、x2
、x1
、x0
运用tables->P_inv[35]
、tables->P_inv[34]
、tables->P_inv[33]
、tables->P_inv[32]
进行非线性逆变换,得到out0
、out1
、out2
、out3
。 - 把
out0
、out1
、out2
、out3
组合成 16 字节的输出数据OUT
。
void Nonlinearwbsm4_encrypt(const unsigned char IN[16], unsigned char OUT[16], const WB_SM4_Tables* tables);
2.3 解密函数的实现
1)输入外部编码
- 把 16 字节的输入 数据
IN
拆分成 4 个 32 位的整数x0
、x1
、x2
、x3
。 - 分别对
x0
、x1
、x2
、x3
运用tables->P[35]
、tables->P[34]
、tables->P[33]
、tables->P[32]
进行非线性变换。
2)执行核心解密
进行 32 轮迭代,不过迭代顺序是从第 31 轮倒着到第 0 轮,每轮迭代包含以下步骤:
- part1:借助查找表
part1_table3
、part1_table2
、part1_table1
对x1
、x2
、x3
进行变换,得到xt1
、xt2
、xt3
。 - part4-1:把
xt1
、xt2
、xt3
按 8 位分割,利用查找表part4_1_table
进行变换,得出x4
。 - part2:将
x4
按 8 位分割,使用查找表part2_table_temp
进行变换,再通过矩阵乘法MatMulNumM32
对结果进行处理,接着利用查找表part2_table
进一步变换,得到中间结果。 - part4-2:把中间结果按 8 位分割,利用查找表
part4_2_table
进行变换,更新x4
。 - part3:借助查找表
part3_table1_dec
、part3_table2
对x0
、x4
进行变换,得到xt0
、xt4
。 - part4-3:把
xt0
、xt4
按 8 位分割,利用查找表part4_3_table_dec
进行变换,更新x4
。 - 更新
x0
、x1
、x2
、x3
的值,即x0 = x1; x1 = x2; x2 = x3; x3 = x4;
。
3)输出外部解码
- 分别对
x3
、x2
、x1
、x0
运用tables->P_inv[0]
、tables->P_inv[1]
、tables->P_inv[2]
、tables->P_inv[3]
进行非线性逆变换,得到out0
、out1
、out2
、out3
。 - 把
out0
、out1
、out2
、out3
组合成 16 字节的输出数据OUT
。
白盒解密函数接口如下:
void Nonlinearwbsm4_decrypt(const unsigned char IN[16], unsigned char OUT[16], const WB_SM4_Tables* tables);
3 安全性分析
3.1 白盒多样性和白盒含混度
为了更好地计算所提出白盒 SM4 实现方法的多样性和含混度[5],需要对所使用的置乱编码的可选择数量进行计算,主要是仿射变换和非线性双射。在此基础上,根据实现方法的结构和生成方式进行具体计算。对于一个上的随机的位可逆仿射变换,所有可能的选择的数量为:
同时,对于一个随机的 8 位非线性双射,输入输出都随机一一对应,因此所有可能的选择的数量为 256!。对于非线性白盒 SM4 实现,每一轮所使用的轮密钥的长度为 32 位,因此每一轮的密钥空间为。根据上文分析,可以计算得到非线性白盒 SM4 实现每一轮各个部分的多样性与含混度如表3-1所示。相较于仿射变换,同样的输入输出位数下非线性双射的可选择数量显著增加了,这极大地提升了实现方法的多样性和含混度,增强了抗暴力攻击的能力,使其安全性有了明显提升。总的来说,从多样性与含混度的计算结果来看,攻击者几乎不可能通过对矩阵和查找表的穷举攻击来获取密钥和置乱编码信息。也就是说,本文所提出的白盒 SM4实现方法可以有效抵抗暴力攻击。更进一步,将该方案的多样性和含混度与已有的方案进行对比。
表3-1 非线性白盒SM4实现的多样性与含混度
阶段 | 多样性 | 含混度 |
---|---|---|
Part 1 | ||
Part 2 | ||
Part 3 | ||
Part 4-1 | ||
Part 4-2 | ||
Part 4-3 |
由于不同实现方案的结构不尽相同,因此很难将他们的多样性与含混度进行统一的比较。考虑到肖-来白盒SM4方案[6]与本论文所提出的两个方案在结构上最为相似,这里将肖-来白盒SM4方案的多样性与含混度列出在表3-2中,以方便比较。通过对比,可以看出相较于肖-来方案,本方案的多样性与含混度均有显著提升,且提升幅度远大于内存占用和加解密所需时间的增长幅度。
表3-2 肖-来方案的多样性与含混度
阶段 | 多样性 | 含混度 |
---|---|---|
Part 1 | ||
Part 2 | ||
Part 3 |
3.2 抗BGE型 攻击
BGE攻击是由Billet、Gilbert和Ech-Chatbi[7]三位研究学者提出的一种攻击方法,最开始提出的目的是攻击Chow等人[5]的白盒AES方案,其主要攻击思路是通过合并相邻轮次的查找表并取消输入输出置乱编码的逆变换,从而暴露出内部的密钥信息。Chow的白盒实现中,输入置乱和输出置乱的逆变换可以相互抵消,导致攻击者可以通过查找表的合并简化运算,最终恢复出密钥。因此,BGE攻击的核心是通过对轮次间的置乱逆变换进行消除,削弱其保护效果。经过分析,BGE 攻击能有效地攻击Chow的算法并观察到密钥信息。
非线性白盒SM4通过引入随机的非线性双射置乱编码来增强算法的安全性。与传统的线性置乱编码不同,非线性双射的设计使得相邻查找表的运算不能简单地合并,置乱编码的逆变换不会像线性编码那样被直接抵消。具体来说,非线性白盒SM4中的置乱编码引入了非线性变换,这些变换增加了攻击者在逆向查找表时的复杂度,即便攻击者通过BGE攻击合并了查找表,非线性编码的存在也使得攻击者无法轻易解析和消除查找表中的置乱信息。非线性白盒SM4通过以下几点有效抵御BGE攻击。
1)非线性双射置乱编码:相比于传统的线性置乱,非线性置乱具有更复杂的数学结构,使得攻击者难以构建有效的代数方程来简化查找表。非线性编码使得置乱逆变换无法被简单消除,从根本上防止了BGE攻击的查找表合并策略,四个并行的 8 位随机非线性双射可以用如式(6)表示。
其中函数的输入输出关系是完全随机的,该变换为双射,输入输出一一对应。
2)引入随机常量的混淆操作:非线性白盒SM4在轮函数的输入置乱中引入了随机常量,这使得即使攻击者试图通过查找表合并来消除置乱的影响,这些随机常量也会干扰他们的攻击过程,使其难以恢复出密钥。
3)复杂的仿射变换与置乱设计:在算法的设计中,仿射变换与非线性置乱相结合,使得攻击者难以通过BGE攻击简化输入输出的映射关系。这种复杂的组合大幅增加了逆向求解密钥的难度。