Merkle Tree(默克爾樹),通常也被稱作Hash Tree。顧名思義,就是存儲hash值的一棵樹。
Merkle樹的葉子是數據塊的hash值(數據塊:文件或者文件的集合)。非葉節點是其對應子節點串聯字符串的hash。
1、Hash
Hash是一個把任意長度的數據映射成固定長度數據的函數。
例如,對於數據完整性校驗,最簡單的方法是對整個數據做Hash運算得到固定長度的Hash值,然后把得到的Hash值公布在網上。
這樣用戶下載到數據之后,對數據再次進行Hash運算,比較運算結果和網上公布的Hash值進行比較,如果兩個Hash值相等,說明下載的數據沒有損壞。
可以這樣做是因為輸入數據的稍微改變就會引起Hash運算結果的面目全非,而且根據Hash值反推原始輸入數據的特征是困難的。
如果從一個穩定的服務器進行下載,采用單一Hash是可取的。但如果數據源不穩定,一旦數據損壞,就需要重新下載,這種下載的效率是很低的。
2、Hash List
在點對點網絡中作數據傳輸的時候,會同時從多個機器上下載數據,而且很多機器可以認為是不穩定或者不可信的。
為了校驗數據的完整性,更好的辦法是把大的文件分割成小的數據塊(例如,把分割成2K為單位的數據塊)。
這樣的好處是,如果小塊數據在傳輸過程中損壞了,那么只要重新下載這一快數據就行了,不用重新下載整個文件。
怎么確定小的數據塊沒有損壞哪?只需要為每個數據塊做Hash。
BT下載的時候,在下載到真正數據之前,我們會先下載一個Hash列表。
那么問題又來了,怎么確定這個Hash列表本身是正確的呢?答案是把每個小塊數據的Hash值拼到一起,然后對這個長字符串在作一次Hash運算,這樣就得到Hash列表的根Hash(Top Hash or Root Hash)。
下載數據的時候,首先從可信的數據源得到正確的根Hash,就可以用它來校驗Hash列表了,然后通過校驗后的Hash列表校驗數據塊。
3、 Merkle Tree
Merkle Tree可以看做Hash List的泛化(Hash List可以看作一種特殊的Merkle Tree,即樹高為2的多叉Merkle Tree)。
在最底層,和哈希列表一樣,我們把數據分成小的數據塊,有相應地哈希和它對應。
但是往上走,並不是直接去運算根哈希,而是把相鄰的兩個哈希合並成一個字符串,然后運算這個字符串的哈希,這樣每兩個哈希就結婚生子,得到了一個”子哈希“。
如果最底層的哈希總數是單數,那到最后必然出現一個單身哈希,這種情況就直接對它進行哈希運算,所以也能得到它的子哈希。
於是往上推,依然是一樣的方式,可以得到數目更少的新一級哈希,最終必然形成一棵倒掛的樹,到了樹根的這個位置,這一代就剩下一個根哈希了,我們把它叫做 Merkle Root。
在p2p網絡下載數據之前,先從可信的源獲得文件的Merkle Tree樹根。一旦獲得了樹根,就可以從其他不可信的源獲取Merkle tree。通過可信的樹根來檢查接受到的Merkle Tree。如果Merkle Tree是損壞的或者虛假的,就從其他源獲得另一個Merkle Tree,直到獲得一個與可信樹根匹配的Merkle Tree。
Merkle Tree和Hash List的主要區別是,可以直接下載並立即驗證Merkle Tree的一個分支。因為可以將文件切分成小的數據塊,這樣如果有一塊數據損壞,僅僅重新下載這個數據塊就行了。
如果文件非常大,Merkle Tree可以一次下載一個分支,然后立即驗證這個分支,如果分支驗證通過,就可以下載其它數據了。而Hash List只有下載整個Hash List才能驗證。
Merkle Tree的特點:
MT是一種樹,大多數是二叉樹,也可以多叉樹,無論是幾叉樹,它都具有樹結構的所有特點;
1、Merkle Tree的葉子節點的value是數據集合的單元數據或者單元數據HASH。
2、非葉子節點的value是根據它下面所有的葉子節點值,然后按照Hash算法計算而得出的。
Merkle Tree的應用:
1、數字簽名
最初Merkle Tree目的是高效的處理Lamport one-time signatures。
每一個Lamport key只能被用來簽名一個消息,但是與Merkle Tree結合可以來簽名多條Merkle。
這種方法成為了一種高效的數字簽名框架,即Merkle Signature Scheme。
2、P2P網絡
在P2P網絡中,Merkle Tree用來確保從其他節點接收的數據塊沒有損壞且沒有被替換,甚至檢查其他節點不會欺騙或者發布虛假的塊。
大家所熟悉的BT下載就是采用了P2P技術來讓客戶端之間進行數據傳輸,一來可以加快數據下載速度,二來減輕下載服務器的負擔。
轉載自:http://www.sohu.com/a/230312547_100123121