區(qū)塊鏈中的哈希函數(shù)
所謂哈希函數(shù)不是指某種特定的函數(shù),而是一類函數(shù),它有各種各樣的實現(xiàn)。
維基百科對散列函數(shù)的定義如下:
散列函數(shù)(英語:Hash function)又稱**散列算法**、**哈希函數(shù)**,是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法。散列函數(shù)把消息或數(shù)據(jù)壓縮成摘要,使得數(shù)據(jù)量變小,將數(shù)據(jù)的格式固定下來。該函數(shù)將數(shù)據(jù)打亂混合,重新創(chuàng)建一個叫做**散列值**(hash values,hash codes,hash sums,或hashes)的指紋。散列值通常用一個短的隨機字母和數(shù)字組成的字符串來代表。好的散列函數(shù)在輸入域中很少出現(xiàn)[散列沖突]。在[散列表]和[數(shù)據(jù)處理]中,不抑制沖突來區(qū)別數(shù)據(jù),會使得數(shù)據(jù)庫記錄更難找到。
通過這個定義,很難看明白這個哈希函數(shù)到底是干什么用的。我們可以先看看這個哈希函數(shù)都有哪些性質,通過對性質的分析,可能會對這個hash函數(shù)有進一步認識,在北大肖臻的區(qū)塊鏈課程中有提到這些性質,我們接下來挨個來看看。

1. 防碰撞性(collision resistance)
當給定不同的輸入?yún)?shù)x,y,且x≠y,但是算出來的結果H(x) = H(y),這樣的現(xiàn)象就被稱為哈希碰撞,產生這種現(xiàn)象的原因,是因為輸入空間遠遠大于輸出空間。
這里的防碰撞特性的意思是,給定一個x可以計算出其哈希值為H(x),但是沒有比較好的辦法,能找到另外一個值y,使它的哈希值H(y)=H(x),也就是人為的制造哈希碰撞。
遍歷所有輸入空間去找到這個值,這種方式就叫做brute-force暴力破解。
哈希函數(shù)一般用來計算digest(摘要信息),可以很好的保證信息不被篡改。
場景分析:比如一個區(qū)塊鏈地址:0xf14f7a4b4ddd69f7bf500ca4c962b03ac95c30fe24e1b4afa87d21e8285c4be9,就是對整個區(qū)塊進行哈希計算,在比特幣中,一個區(qū)塊大概可以包含4000比交易,但是通過這個地址,就可以完成對這4000比交易的驗證,這里就體現(xiàn)了哈希函數(shù)的壓縮特性和防碰撞特性。

2. 隱藏性(Hiding)
哈希函數(shù)的計算過程是單向不可逆的。也就是通過可以推出H(x),但是沒有辦法通過H(x)這個結果反推x的值,也就是說,哈希值H(x)沒有泄露輸入的x的任何信息。也就是x的信息被安全的隱藏起來。
場景分析:還是拿這個區(qū)塊鏈地址來看:0xf14f7a4b4ddd69f7bf500ca4c962b03ac95c30fe24e1b4afa87d21e8285c4be9
假設這個區(qū)塊中包含了4000比交易,因為哈希函數(shù)具有的壓縮特性,使得根本沒辦法從這個地址,恢復出4000比交易的完整信息。這也就說明,這個地址,沒有泄露區(qū)塊中任何一筆交易的信息,體現(xiàn)的就是隱藏性(單向性)。

3. 謎題友好(puzzlefriendly)
無法通過控制輸入值x來獲得任意想要的輸出值H(x),但是一旦找到了某個H(x),其他人驗證,又是佷容易的。
場景分析:在區(qū)塊鏈中,某個區(qū)塊被打包后,會在全網(wǎng)廣播。當其他節(jié)點拿到算出來的hash值和區(qū)塊的完整交易信息后,需要對它們做驗證,驗證的方式就用這些交易信息再次計算hash值,再將自己計算的hash值和廣播的hash值比對,來確定廣播的信息是否可信。
下圖為wiki中,對常見的哈希函數(shù)的對比分析:

在區(qū)塊鏈的項目實現(xiàn)中,SHA256占據(jù)了很重要的位置,后面會貼出在btc和eth中,SHA256的使用代碼,足可見此方法的奠基性。

SHA256簡介
SHA-2,名稱來自于安全散列算法2(英語:Secure Hash Algorithm 2)的縮寫,一種密碼散列函數(shù)算法標準。SHA256屬于SHA-2,SHA-2總共包括SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256這六個標準。
SHA-256和SHA-512是很新的散列函數(shù),前者以定義一個word為32位,后者則定義一個word為64位。它們分別使用了不同的偏移量,或用不同的常量,然而,實際上二者結構是相同的,只在循環(huán)執(zhí)行的次數(shù)上有所差異。SHA-224以及SHA-384則是前述二種散列函數(shù)的截短版,利用不同的初始值做計算。
對SHA256底層有興趣的,可以進一步學習算法實現(xiàn)的文章。比如:[大白話講解SHA256](https://juejin.cn/post/7128056401087168519)
在btcd(比特幣的go語言實現(xiàn))項目中,調用的hash方法的代碼是:
在go-ethereum項目依賴golang.org/x/crypto@v0.1.0/sha3/hashes.go中的代碼是:
我們知道MD5 與 SHA-1 算法已被攻破,不應該再被用于新的用途;SHA-2 與 SHA-3 還是安全的,可以使用。
SHA-2系列包括:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
SHA-3系列包括:SHA3-224、SHA3-256、SHA3-384、SHA3-512。

從源代碼中可以看出,以太坊用的是sha3-256,而比特幣用的是sha-256。