摘要:本文档对Intel提出的基于AES-NI实现SM4算法的专利进行分析研究,记录其原理,并列出实现代码的具体实现流程。
Intel的方案的核心思想是:
1)使用SIMD指令进行多个分组数据的并行处理;
2)使用AESENCLAST来完成SM4的S变换。
AESENCLAST指令执行AES加密的最后一轮,其具体功能是对16字节的AES状态数据依次做S变换、行移位、异或子密钥这三个操作。但该指令是对16个字节进行AES的S变换,而SM4的S变换仅对4个字节执行,因此需由4个SM4分组来并行实施以凑齐16字节(每个SM4分组取32比特/4字节,4个分组取128比特/16字节),以匹配一条AESENCLAST指令。
AES的S变换的数学结构为Sr(x) = Ar × Invr(x) + Cr。【用下标r表示AES的对应记号】
SM4的S变换的数学结构为Sm(x) = Am × Invm( (Am(x) + Cm) ) + Cm。【用下标m表示SM4的对应记号】
对SM4的S变换,记
上述表达式中计算Inv是最复杂最耗时的运算。AES中可利用AES的硬件指令快速计算Inv,但SM4没有这样的指令。一种办法是借助有限域的同构映射,先把SM4的元素映射到AES中,在AES中利用硬件指令计算Inv,最后再映射回来。如下图1。
图1 两个算法的S变换以及同构映射图
如前所述,用AES计算SM4的S变换,就是借助有限域的同构映射,
1)先把SM4的元素映射到AES中,
2)在AES中利用硬件指令计算Inv,
3)最后再映射回来。
围绕以上三个步骤,用AES计算SM4的S变换的详细情况包括如下图列出的四个台阶。
图2 用AES计算SM4的S变换的规划图
如下图,从y计算出z,有两种方案(如下图):
方案1:如下图蓝色虚线,直接计算SM4的inv,即z = Invm(y)
方案2:如下图红色虚线指定的路线,利用同构映射T映射到AES这边,再做AES与上的inv,最后再映射回来,即z = T-1Invr(T(y))
所以,
Invm(y) = z = T-1Invr(T(y))
图3 利用AES的Inv运算计算SM4的INV运算
AES算法的Invr没有单独的指令实现,如果利用AES完整的S变换(更靠近可用的AESENCLAST指令),那么需要将Sr(x)值抵消掉Invr之后的两个操作+Cm和Am×,如下图。所以,从y计算出z的两种方案调整如下:
方案1:无调整,如下图蓝色虚线,直接计算SM4的inv,即z = Invm(y)。
方案2:有调整,如下图红色虚线指定的路线——利用同构映射T映射到AES这边,再做AES与上的S变换,接着抵消掉+Cm(逆运算仍然是+Cm)和Am×(逆运算是A-1m×),最后再映射回来,即
z = T-1 A-1r× ( Sr(T(y)) + Cr ) = T-1 A-1r× Sr(T(y)) + T-1 A-1r Cr。
所以
Invm(y) = z = T-1 A-1r× Sr(T(y)) + T-1 A-1r Cr
图4 利用AES的S变换计算SM4的Inv
将步骤二得到的Invm(y)的算式带入SM4的S变换的表达式,就可以得到完整的SM4的S变换(如下图红色虚线):
Sm(x)
= Am × Invm(y) + Cm 【SM4的S变换的表达式】
= Am (T-1 A-1r× Sr(T(y)) + T-1 A-1r Cr ) + Cm【代入第二步结果表达式】
= Am T-1 A-1r× Sr(T(Am(x)+ Cm)) + Am T-1 A-1r Cr ) + Cm【代入y的表达式】
= Am T-1 A-1r× Sr(T×Am(x)+ T×Cm)) + Am T-1 A-1r Cr ) + Cm【展开】
图5 利用AES的S变换计算SM4的Inv
上面得到的结果结果需要简化才能用于实际中。
首先,能合并的变换尽可能合并,以AES的S变换为分界线,
其次,因为使用的是AESENCLAST指令,但只需要其中的S变换部分,所以,行移位和子密钥异或需要消除。其中,行移位可利用Shuffle指令去除,子密钥异或可将子密钥设置为全0即可。
第一步:执行前变换:x(1) = T×Am(x)+ T×Cm。
第二步:执行AES-NI指令:x(2) = AESENCLAST(x(1), 0)。
第三步:执行抵消行变换:采用Shuffle指令,x(3) = Shuffle(x(2), *),本步结果为对应的AES的S变换值。
第四步:执行后变换:x(4) = Am T-1 A-1r×x(3) + ( Am T-1 A-1r Cr + Cm ),输出x(4)作为SM4的S运算结果。
图6简化运算和修订AESENCLAST
SM4-AES-NI实方案
输入:
输出:
步骤
第1步:加载输入数据
B(j) = (X0(j), X1(j), X2(j), X3(j)),j = 0, 1, …, Z-1。
X0 = (X0(0), X0(1), …,X0(Z-1))
X1 = (X1(0), X1(1), …,X1(Z-1))
X2 = (X2(0), X2(1), …,X2(Z-1))
X3 = (X3(0), X3(1), …,X3(Z-1))
图 4m比特数据的排列方式
(行为按分组大小排列,列为按m比特的X0、X1、X2、X3排列)
步骤2:执行32次迭代。对轮计数器i = 0, 1, 2, …, 31执行如下轮迭代:
K(j) = (K0(j), K1(j) , …, K31(j)),j = 0, 1, …, Z-1
取第i轮的m比特子密钥为rki = (Ki(0), Ki(1) , …, Ki(Z-1))。
T = X1⊕X2⊕X3⊕rki
T = SBOX(T)见1.3节
T= T⊕(T<<<2)⊕(T <<<10)⊕(T <<<18)⊕(T <<< 24)
代码中优化为: T= (T⊕(T <<< 24)) ⊕ (((T)⊕(T <<<8)⊕(T <<<16))<<<2) 其中:
|
图 线性变换层的优化实现
步骤3:保存并输出数据。