SM3密码杂凑算法由国家密码管理局于2010年12月17日发布,对于现在的使用环境来说,是一个比较过时的密码算法了,毕竟现代社会总是日新月异的,在这十几年的时间里,信息行业得到了空前的发展,人们在享受着互联网便捷的同时也对自身的数据安全有了更多的思考,因此在这十几年里又有安全等级更高的的密码算法替代SM3,以满足现代人们生活生产的需要。在这篇文章中,我将分析SM3如何实现的以及与主流密码方案的异同。
- SM3分析
SM3诞生是为了适应商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成,同时还可为安全产品生产商提供产品和技术的标准定位以及标准化的参考,提高安全产品的可信性与互操作性。SM3是哈希算法的一种,安全性及效率与SHA-256相当,同时需要注意的是:哈希算法是单向函数,它将任意长度的输入消息转换为固定长度的哈希值,具有不可逆性和抗碰撞性,所以我们无法从哈希值还原出原始的输入消息,也无法对哈希值进行解密操作,因此,对于SM3来说,不存在"解密"的概念。SM3实现的是对二进制流的加密,所以在使用SM3时,要把待加密的消息先转成二进制的形式,随后经过填充、分块、迭代压缩,生成杂凑值,杂凑值长度为256比特。
(1)填充:
假设消息m的长度为L比特。首先将比特“1”添加到消息的末尾,在添加k个“0”,k是满足L + 1 + k ≡ 448(mod 512)的最小的非负整数。然后再添加一个64位比特串,该比特串是长度L的二进制表示。填充的消息m’的比特长度为512的倍数。
注意到,SM3算法在这里采用了模运算来增加算法的安全性,模运算是一种对数据进行取模运算的操作,可以有效地减小数据的大小,从而增加算法的难度和安全性。
例如:对消息01100001 01100010 01100011,其长度L=24,经填充得到比特串:
01100001 01100010 01100011 1 00··············00 00············011000
423个“0” 长度L=24的二进制表示示
同时,若消息m的长度L超过了512,则每512个比特又被分成一块,每一块由四部分构成:消息m的二进制串 + 1 + k个“0” + 64位比特串。
(2)迭代压缩:
迭代压缩又有三个过程:迭代、消息扩展、压缩。
1、迭代:
将填充后的消息m’按512比特进行分组:m’= B(0)B(1) · · · B(n−1)。其中n=(L+1+k)/512。
对m’按以下方式迭代:
FOR i=0 TO n-1
V(i+1) = CF(V(i),B(i))
ENDFOR
其中,CF是后面要用的压缩函数,V(0)是256比特初始值IV,B(i)是填充后每512比特一块,迭代结果为V(n)。如果说,消息m的长度L没有超过512比特,那么消息只会被分成一块,为B(0),同时,迭代只会进行一次,迭代结果为V(1)。
IV = 7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e
A B C D E F G H
2、消息扩展
将分块B(i)按以下方法扩展生成132个字:W0,W1,W2,,,,W67,W0’,W1’,W2’,,,W63’。(每1个字占32比特)用于压缩函数CF:
(a)将分块B(i)划分为16个字(512=16*32):W0,W1,W2,···,W15。
(b)FOR j=16 TO 67
Wj ← P1(Wj-16 ⊕ Wj-9 ⊕ (Wj-3<<<15)) ⊕ (Wj-13<<<7) ⊕ Wj-6
ENDFOR
(c)FOR j=0 TO 63
Wj’= Wj ⊕ Wj+4
ENDFOR
Wj等于箭头后面的计算结果,Wj-3<<<15意思是Wj-3循环左移15个比特,Wj-13<<<7也是类似的。使用向左循环移位,这改变了数据的排列数序,增加了算法的随机性,难以破解。
- 压缩函数
令A,B,C,D,E,F,G,H为寄存器,SS1,SS2,TT1,TT2为中间变量,压缩函数V(i+1)=CF(V(i),B(i)),0 ≤ i ≤ n−1。计算过程如下:
ABCDEFGH ← V(i)
FOR j=0 TO 63
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)
ENDFOR
V(i+1) ← ABCDEFGH ⊕ V(i)
首先将V(i)的值向左赋值给ABCDEFGH,最初i=0,也就是初始值IV。然后开始63次循环,经过一轮又一轮的循环,ABCDEFGH的值也在发生变化,循环结束后,将最后一轮的ABCDEFGH与初始值IV异或,向左赋值得到V(i+1)。在这里,Tj是一个常量,FFj、GGj、P0都是函数,FFj和GGj都是布尔函数,PO是置换函数。
在消息扩展和压缩函数中,SM3算法采用了多轮非线性函数来增加算法的复杂性和抗攻击性,这些非线性函数包括置换、置换运算和S盒等,这些函数能够有效地混淆输入数据,使得原始输入数据难以被复原。
到此,计算已经完成,我们可以得到256比特的杂凑值:ABCDEFGH ← V(n)
二、SM3与主流密码方案的异同
经过上述内容的分析,可以看出迭代压缩是整个SM3算法中最复杂的部分,前面的填充、分块、消息扩展其实都是为迭代压缩做准备,每一块固定为512比特(一块为16个字)也是为了方便压缩。如果消息m的长度L超出512比特,那么分块时,就不只是分成一块,况且每块又会扩展成132个字,所以在迭代压缩时,计算量是相当大的并且是复杂的。
所以,与主流密码方案相比,相同的地方在于都是用了比较复杂的运算,在加密过程中,使用了置换、移位、模运算、扩展等方法,如果一次不够,担心不够安全,那就多做几轮、几十轮。目的只有一个:让原始数据变得不同,让人一看到就不知所云。例如,椭圆曲线算法ECC,输入的单个明文,加密后密文却可以变成一个坐标,或者是空间中某个位置,正常人来看就是一个坐标,却不知道实际是加密后的内容。这也算是密码的同性吧,达到混淆的目的,提高数据安全等级。
当然,SM3与主流的公钥算法、对称算法也有不同之处。首先,它没有公私钥,算法内容是完全公开的。其次,它利用的是哈希函数单向性,加密后的内容是不可解密的,所以用途不同,它不适用于信息加解密,而是适用于数字签名、生成随机数、消息认证码。
总结下来,SM3算法是一种不可被解密的算法,常用于生成消息的摘要和校验数据完整性,而不是用于加解密。所以,如果需要进行加密和解密操作,应该选择主流的密码方案。