區塊鏈中的密碼學(1):散列算法 SHA256算法分析與實現

在很多技術人員的眼中,區塊鏈並不是一種新的技術,而是過去很多年計算機技術的組合運用。而在這個方方面面技術的運用上,基於密碼學的加密算法可以說是區塊鏈各種特點得以表現的根本,一旦目前使用的加密算法被證實可以破解,那麼現有的區塊鏈技術很有可能土崩瓦解。本文所要講述的就是目前區塊鏈中運用最廣的加密算法:SHA256。

SHA是一個密碼散列函數家族,是英文Secure Hash Algorithm的縮寫。由美國國家安全局(NSA)所設計,並由美國國家標準與技術研究院(NIST)發佈。本文的主角SHA256算法就是這個家族中的一員。在此之前的SHA0,SHA1都被證明是可以破解的,目前SHA2以及SHA3尚未被證實可以破解。這裏引申一下,在密碼學的定義中,所謂可以破解,即是計算複雜度少於暴力破解所需要的計算複雜度。SHA256中的256取的這種算法的摘要長度。下面會具體講一下SHA256的實現原理。

SHA256算法的設計思路主要是依賴於一個優秀的HASH散列算法的特點:任何微小的輸入都有可能對輸出產生巨大的影響,以及HASH算法極低的碰撞概率。

常量定義:

SHA256算法中首先規定了8個哈希初值和64個哈希常量。8個哈希初值取的是自然數中前8個質數(2,3,5,7,11,13,17,19)的平方根的小數部分的前32bit的值。例如:

取小數部分:0.414213562373095048(用16進製表示)= 6\times16^{-1}+a\times16^{-2}+0\times16^{-3}+...

所以8個哈希初值的第一個可以表示爲: h0 : = 0X6a09e667。最終取到的8個哈希初值分別是:

H0= 0x6a09e667 
H1 = 0xbb67ae85  
H2 = 0x3c6ef372 
H3 = 0xa54ff53a 
H4 = 0x510e527f 
H5 = 0x9b05688c 
H6 = 0x1f83d9ab 
H7 = 0x5be0cd19

在看前面8個哈希初值的定義,64個哈希常量的定義是取自然數中前64個質數的立方根的小數部分的前32bit的值。這裏就不貼出來了,瞭解定義即可。細心的讀者應該能發現,8個哈希初值,每個32位,總長度對應的就是SHA256算法的最後結果的長度。

邏輯函數定義:

SHA256算法定義了6中邏輯函數,這6個邏輯函數的作用這裏先簡單瞭解,後續的代碼部分會看到如何使用。

備註: AND 表示”與“運算,NOT 表示:”或“運算,XOR 表示”異或“運算。ROTR^2(X)表示對X進行循環右移兩位,SHR^3(X)表示對X右移三位。函數的輸入都是32bit的字。

CH(x, y, z) = (x AND y) XOR ( (NOT x) AND z)  
MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)  
BSIG0(x) = ROTR^2(x) XOR ROTR^13(x) XOR ROTR^22(x)  
BSIG1(x) = ROTR^6(x) XOR ROTR^11(x) XOR ROTR^25(x)  
SSIG0(x) = ROTR^7(x) XOR ROTR^18(x) XOR SHR^3(x)  
SSIG1(x) = ROTR^17(x) XOR ROTR^19(x) XOR SHR^10(x)

算法過程:

補位:

補位的目的是爲了使消息長度滿足: (消息原始長度+1+K) mod 512 = 448 這個公式。爲什麼是448,目的是爲了後續留有64位的長度來表示消息的長度,SHA256支持的消息長度是不大於2的64次方。1表示補位第一步補的一個位,K表示需要補的0的個數。補位的第一步是不管消息長度多少(即使對512去模等於448),都在末尾補一個1。

假設原始消息是這樣: 01111101 01110000 11110000 00000001

補位第一步後的消息: 01111101 01110000 11110000 00000001 1

根據上面的解釋很容易算出需要補 415個0。

補長度:

補充的長度一般是固定的64bit,用來表示消息的初始長度。上面輸入的長度是32位,轉換成16進制是100000。所以將會把100000補在上面的消息後面,不足64位用0補。

計算過程:

整體思路:把消息分成大小512bit的N份,取第一個數據塊的數據,分成16份32bit的數組。最開始的8個哈希初值H(0)經過第一個消息塊數據運算得到H(1),經過第二個消息塊數據運算得到H(2),一次循環,直到得到H(N),就是最後得到的信息摘要。

詳細過程如下:

1)首先使用一個256-bit 的緩存來存放該散列函數的中間及最終結果。我們前面提到SHA256中定義了8個初始值,這8個初始值用a,b,c,d,e,f,g,h表示:

a=0x6a09e667, b=0xbb67ae85,

c=0x3c6ef372, d=0xa54ff53a,

e=0x510e527f, f=0x9b05688

c, g=0x1f83d9ab, h=0x5be0cd19。

2)把補長過的消息進行拆分成N個512bit數據。首先計算函數的外部有個大的循環,形如: For i =1 to N;

3 ) 在每一次的循環裏,需要給函數W(t)的輸入t爲0到63的結果賦值,即W(0),W(1),W(2)...W(63)。其中W(0)到W(15)的值爲當前快消息被拆分的16個值(前面提到的每個塊分成16個32bit的數據)。然後W(16)到W(63)取的值爲依賴前面16個值產生,具體算法如下 :

For t = 0 to 15
Wt = M(i)t   //賦值W(t)的前16個值
For t = 16 to 63
Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(w(t-15)) + W(t-16) //利用W(t)前面的16個值計算後面的值

4)利用第三步取到的W(t)的64個值,進行64次循環,打亂原有的順序。過程中有一些中間變量,但是目的是爲了重新給a,b,c,d,e,f,g,h賦值。代碼過程:

For t = 0 to 63     
T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt //這裏的Wt就是在文章開頭定義的64個哈希常量。
T2 = BSIG0(a) + MAJ(a,b,c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2

可以看到,利用之前介紹的邏輯函數和第三步的運算結果,重新計算了a,b,c,d,e,f,g,h的值。

5) 最後一步就是根據第四步重新賦值的8個變量得出這個塊的SHA256結果。

通過上一步的H(i-1)0到H(i-1)7的值計算H(i)0到H(i)7的值。

H(i)0 = a + H(i-1)0    //a是一個32bit的值,H(i-1)0也是一個32bit的值

H(i)1 = b + H(i-1)1

H(i)2 = c + H(i-1)2

H(i)3 = d + H(i-1)3

H(i)4 = e + H(i-1)4

H(i)5 = f + H(i-1)5

H(i)6 = g + H(i-1)6

H(i)7 = h + H(i-1)7

到這裏,第一次循環就結束了,還記得之前提過的”外部有個大的循環,形如: For i =1 to N “ 嗎?在SHA256中,消息的長度越長,循環的次數也越多。經過N此循環得到H(N)0,H(N)1,H(N)2,...H(N)7,8個32位的數拼接起來就形成了SHA256算法的最終結果:一個長度爲256位的消息摘要。

在比特幣中,SHA256運用在了錢包地址的產生,也是實現pow共識機制的主要手段。就目前來說,2的256次方近似於10的77次方,10的77次方有多大?到目前爲止,人類可觀測的宇宙中的原子數約爲10的80次方,這種數量級的散列算法想要通過碰撞來***基本是不可能的。這也是目前爲什麼SHA256算法得到普遍應用的原因之一。

本文首發於blockgeek.org

BG論壇思考題

按照慣例,爲大家隨機挑選一條Blockgeek.org上的技術問題,有興趣的同學可以挑戰一下,來吧,別猶豫!

【提問】SHA256算法還在哪些應用中有所使用?

作者簡介

FigoBlockgeek.org 簽約技術作者,區塊鏈重度愛好者。熱衷於區塊鏈技術推廣,參與hyperledger fabric中文社區翻譯,對以太坊,EOS,HPB,星雲等各大公鏈有深入研究。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章