使用X64汇编语言编写高性能国密SM3散列算法实现代码(一)

我只是一个虾纸丫 提交于 2019-12-18 11:52:52

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

文中使用的C语言风格运算符说明:

=       赋值
==      等于
<       小于
<=      小于等于
~       按位求反
&       按位与
^       按位异或
|       按位或
<<<     循环左移
>>>     循环右移

4.1     初始值
这个没什么好说的,照抄标准文档即可:

7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e

4.2     常量
标准文档对于常量Tj的描述摘要如下:

0 <= j <= 15    Tj = 0x79cc4519
16 <= j <= 63   Tj = 0x7a879d8a

这个j是个整数,其含义为压缩函数的循环次数(依次取值从0到63共计64次),在压缩函数中Tj要循环位移j次后进行加法运算,因此Tj变成常量数组如下:

00 <= j <= 15
79cc4519 f3988a32 e7311465 ce6228cb 9cc45197 3988a32f 7311465e e6228cbc
cc451979 988a32f3 311465e7 6228cbce c451979c 88a32f39 11465e73 228cbce6

16 <= j <= 47
9d8a7a87 3b14f50f 7629ea1e ec53d43c d8a7a879 b14f50f3 629ea1e7 c53d43ce
8a7a879d 14f50f3b 29ea1e76 53d43cec a7a879d8 4f50f3b1 9ea1e762 3d43cec5
7a879d8a f50f3b14 ea1e7629 d43cec53 a879d8a7 50f3b14f a1e7629e 43cec53d
879d8a7a 0f3b14f5 1e7629ea 3cec53d4 79d8a7a8 f3b14f50 e7629ea1 cec53d43

48 <= j <= 63
9d8a7a87 3b14f50f 7629ea1e ec53d43c d8a7a879 b14f50f3 629ea1e7 c53d43ce
8a7a879d 14f50f3b 29ea1e76 53d43cec a7a879d8 4f50f3b1 9ea1e762 3d43cec5

使用此数组时不再对Tj进行循环位移运算。

4.3     布尔函数
标准文档对布尔函数的描述摘要如下:

0 <= j <= 15    FFj(X,Y,Z) = X ^ Y ^ Z
16 <= j <= 63   FFj(X,Y,Z) = (X & Y) | (X & Z) | (Y & Z)
0 <= j <= 15    GGj(X,Y,Z) = X ^ Y ^ Z
16 <= j <= 63   GGj(X,Y,Z) = (X & Y) |(~X & Z)

根据逻辑代数运算规则优化FFj如下:

16 <= j <= 63   FFj(X,Y,Z) = (X & (Y | Z)) | (Y & Z)

4.4     置换函数
标准文档对布尔函数的描述摘要如下:

P0(X) = X ^ (X <<< 9) ^ (X <<< 17)
P1(X) = X ^ (X <<< 15) ^ (X <<< 23)

使用寄存器运算时等效变换如下:

P0(X) = X ^ (X <<< 9) ^ ((X <<< 9) <<< 8)
P1(X) = X ^ (X <<< 15) ^ ((X <<< 15) <<< 8)

5.3.2   消息扩展
标准文档对消息扩展的描述摘要如下:

将消息分组(固定长度为512位)扩展生成132个字, 用于压缩函数CF。

原始文档在消息扩展完成后,使用了两个数组Wj[68]和Wj'[64]保存数据,为了最大限度发挥X64处理器性能,将数组Wj的规模从68缩减到20,将数组Wj'取消,相应的,将修改压缩函数CF以适应此变化。

5.3.3   压缩函数
压缩函数CF是整个算法的核心,标准文档不太像是给X64系列处理器专门设计的,在保证算法实现正确的前提下,对算法实现流程进行了大幅度地调整。
标准文档摘录如下:

SS1 = ((A <<< 12) + E + (Tj <<< j)) <<< 7
SS2 = SS1 ^ (A <<< 12)
TT1 = FFj(A,B,C) + D + SS2 + Wj'
TT2 = GGj(E,F,G) + H + SS1 + Wj
D   = C
C   = B <<< 9
B   = A
A   = TT1
H   = G
G   = F <<< 19
F   = E
E   = P0(TT2)

本文调整运算流程如下:
 

SS0 = A <<< 12
SS1 = (SS0 + E + Tj) <<< 7
TT2 = GGj(E,F,G) + H + SS1 + W[j]
TT2 = P0(TT2)
SS2 = SS1 ^ SS0
Wj' = W[j] ^ W[j+4]
TT1 = FFj(A,B,C) + D + SS2 + Wj'
B   = B <<< 9
F   = F >>> 13

调整流程的原则是不改变数值依赖关系,这里使用了只有在汇编语言编程才有的寄存器重定义技巧,只有阅读对应的完整代码和注释才能彻底理解。所谓重定义,是指寄存器在完成运算后改变了其算法定义的情形,可以借此缩减部分赋值指令,实际效果就是省掉了标准文档中的四个赋值操作:

D   = C
B   = A
H   = G
F   = E

相应的,在下一轮迭代中,要记住谁改名了,千万不要搞错了。

(未完待续)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!