默克爾樹(Merkle Tree)總結

目錄

爲什麼要有默克爾樹

簡介

Merkle Tree的特點

圖解

創建樹

檢索-文件夾比較

檢索-防僞

更新

插入刪除

應用

數字簽名

P2P網絡

可信計算

區塊鏈-簡單驗證支付


爲什麼要有默克爾樹

Hash是一個把任意長度的數據映射成固定長度數據的函數[2]。例如,對於數據完整性校驗,最簡單的方法是對整個數據做Hash運算得到固定長度的Hash值,然後把得到的Hash值公佈在網上,這樣用戶下載到數據之後,對數據再次進行Hash運算,比較運算結果和網上公佈的Hash值進行比較,如果兩個Hash值相等,說明下載的數據沒有損壞。可以這樣做是因爲輸入數據的稍微改變就會引起Hash運算結果的面目全非,而且根據Hash值反推原始輸入數據的特徵是困難的。

如果從一個穩定的服務器進行下載,採用單一Hash是可取的。但如果數據源不穩定,一旦數據損壞,就需要重新下載,這種下載的效率是很低的。

在點對點網絡中作數據傳輸的時候,會同時從多個機器上下載數據,而且很多機器可以認爲是不穩定或者不可信的。爲了校驗數據的完整性,更好的辦法是把大的文件分割成小的數據塊(例如,把分割成2K爲單位的數據塊)。這樣的好處是,如果小塊數據在傳輸過程中損壞了,那麼只要重新下載這一快數據就行了,不用重新下載整個文件。

怎麼確定小的數據塊沒有損壞哪?只需要爲每個數據塊做Hash。BT下載的時候,在下載到真正數據之前,我們會先下載一個Hash列表。那麼問題又來了,怎麼確定這個Hash列表本事是正確的哪?答案是把每個小塊數據的Hash值拼到一起,然後對這個長字符串在作一次Hash運算,這樣就得到Hash列表的根Hash(Top Hash or Root Hash)。下載數據的時候,首先從可信的數據源得到正確的根Hash,就可以用它來校驗Hash列表了,然後通過校驗後的Hash列表校驗數據塊。

簡介

默克爾樹,Merkle Tree可以看做Hash List的泛化(Hash List可以看作一種特殊的Merkle Tree,即樹高爲2的多叉Merkle Tree)。

在最底層,和哈希列表一樣,我們把數據分成小的數據塊,有相應地哈希和它對應。但是往上走,並不是直接去運算根哈希,而是把相鄰的兩個哈希合併成一個字符串,然後運算這個字符串的哈希,這樣每兩個哈希就結婚生子,得到了一個”子哈希“如果最底層的哈希總數是單數,那到最後必然出現一個單身哈希,這種情況就直接對它進行哈希運算,所以也能得到它的子哈希。於是往上推,依然是一樣的方式,可以得到數目更少的新一級哈希,最終必然形成一棵倒掛的樹到了樹根的這個位置,這一代就剩下一個根哈希了,我們把它叫做 Merkle Root[3]。

在p2p網絡下載網絡之前,先從可信的源獲得文件的Merkle Tree樹根。一旦獲得了樹根,就可以從其他從不可信的源獲取Merkle tree。通過可信的樹根來檢查接受到的Merkle Tree。如果Merkle Tree是損壞的或者虛假的,就從其他源獲得另一個Merkle Tree,直到獲得一個與可信樹根匹配的Merkle Tree。

Merkle Tree和Hash List的主要區別是,可以直接下載並立即驗證Merkle Tree的一個分支。因爲可以將文件切分成小的數據塊,這樣如果有一塊數據損壞,僅僅重新下載這個數據塊就行了。如果文件非常大,那麼Merkle tree和Hash list都很到,但是Merkle tree可以一次下載一個分支,然後立即驗證這個分支,如果分支驗證通過,就可以下載數據了。而Hash list只有下載整個hash list才能驗證。 

 

Merkle Tree的特點

MT是一種樹,大多數是二叉樹,也可以多叉樹,無論是幾叉樹,它都具有樹結構的所有特點;

Merkle Tree的葉子節點的value是數據集合的單元數據或者單元數據HASH。默克爾樹的基礎數據不是固定的,想存什麼數據由你說了算,因爲它只要數據經過哈希運算得到的hash值。

非葉子節點的value是根據它下面所有的葉子節點值,然後按照Hash算法計算而得出的。默克爾樹是從下往上逐層計算的,就是說每個中間節點是根據相鄰的兩個葉子節點組合計算得出的,而根節點是根據兩個中間節點組合計算得出的,所以葉子節點是基礎。

圖解

創建樹

加入最底層有9個數據塊。

step1:(紅色線)對數據塊做hash運算Node0i = hash(Data0i), i=1,2,…,9

step2: (橙色線)相鄰兩個hash塊串聯,然後做hash運算,Node1((i+1)/2) = hash(Node0i+Node0(i+1)), i=1,3,5,7;對於i=9, Node1((i+1)/2) = hash(Node0i)

step3: (黃色線)重複step2

step4:(綠色線)重複step2

step5:(藍色線)重複step2,生成Merkle Tree Root 

 

檢索-文件夾比較

爲了更好理解,我們假設有A和B兩臺機器,A需要與B相同目錄下有8個文件,文件分別是f1 f2 f3 ….f8。這個時候我們就可以通過Merkle Tree來進行快速比較。假設我們在文件創建的時候每個機器都構建了一個Merkle Tree。具體如下圖: 

從上圖可得知,葉子節點node7的value = hash(f1),是f1文件的HASH;而其父親節點node3的value = hash(v7, v8),也就是其子節點node7 node8的值得HASH。就是這樣表示一個層級運算關係。root節點的value其實是所有葉子節點的value的唯一特徵。

  假如A上的文件5與B上的不一樣。我們怎麼通過兩個機器的merkle treee信息找到不相同的文件? 這個比較檢索過程如下:

  Step1. 首先比較v0是否相同,如果不同,檢索其孩子node1和node2.

  Step2. v1 相同,v2不同。檢索node2的孩子node5 node6;

  Step3. v5不同,v6相同,檢索比較node5的孩子node 11 和node 12

  Step4. v11不同,v12相同。node 11爲葉子節點,獲取其目錄信息

  Step5. 檢索比較完畢。

  以上過程的理論複雜度是Log(N)。過程描述圖如下:

檢索-防僞

如果一個惡意的 用戶試圖在默克爾樹的底部替換一個假的交易, 這個更改將導致上面的節點發生變化,然後上面的節點的變化又會導致上上面的節點發生變化,最終改變這個數根節點,因此也改變了這區塊的哈 希,導致這個協議把它註冊成一個完全不同的區塊 (幾乎可以肯定是一個無效的工作證明).

更新

對於Merkle Tree數據塊的更新操作其實是很簡單的,更新完數據塊,然後接着更新其到樹根路徑上的Hash值就可以了,這樣不會改變Merkle Tree的結構。

插入刪除

這是原來的默克爾樹,總共8個葉子節點,現在插入節點0

有兩種辦法

死辦法

生成平衡樹的方法

Merkle Tree的插入和刪除操作其實是一個工程上的問題,不同問題會有不同的插入方法。如果要確保樹是平衡的或者是樹高是log(n)的,可以用任何的標準的平衡二叉樹的模式,如AVL樹,紅黑樹,伸展樹,2-3樹等。這些平衡二叉樹的更新模式可以在O(lgn)時間內完成插入操作,並且能保證樹高是O(lgn)的。那麼很容易可以看出更新所有的Merkle Hash可以在O((lgn)2)時間內完成(對於每個節點如要更新從它到樹根O(lgn)個節點,而爲了滿足樹高的要求需要更新O(lgn)個節點)。如果仔細分析的話,更新所有的hash實際上可以在O(lgn)時間內完成,因爲要改變的所有節點都是相關聯的,即他們要不是都在從某個葉節點到樹根的一條路徑上,或者這種情況相近。

實際上Merkle Tree的結構(是否平衡,樹高限制多少)在大多數應用中並不重要,而且保持數據塊的順序也在大多數應用中也不需要。因此,可以根據具體應用的情況,設計自己的插入和刪除操作。一個通用的Merkle Tree插入刪除操作是沒有意義的。(因爲一般默克爾樹根據它的應用和特性,只有創建和檢索操作)

應用

數字簽名

最初Merkle Tree目的是高效的處理Lamport one-time signatures。 每一個Lamport key只能被用來簽名一個消息,但是與Merkle tree結合可以來簽名多條Merkle。這種方法成爲了一種高效的數字簽名框架,即Merkle Signature Scheme。

P2P網絡

P2P網絡中,Merkle Tree用來確保從其他節點接受的數據塊沒有損壞且沒有被替換,甚至檢查其他節點不會欺騙或者發佈虛假的塊。大家所熟悉的BT下載就是採用了P2P技術來讓客戶端之間進行數據傳輸,一來可以加快數據下載速度,二來減輕下載服務器的負擔。BT即BitTorrent,是一種中心索引式的P2P文件分分析通信協議。

要進下載必須從中心索引服務器獲取一個擴展名爲torrent的索引文件(即大家所說的種子),torrent文件包含了要共享文件的信息,包括文件名,大小,文件的Hash信息和一個指向Tracker的URL。Torrent文件中的Hash信息是每一塊要下載的文件內容的加密摘要,這些摘要也可運行在下載的時候進行驗證。大的torrent文件是Web服務器的瓶頸,而且也不能直接被包含在RSS或gossiped around(用流言傳播協議進行傳播)。一個相關的問題是大數據塊的使用,因爲爲了保持torrent文件的非常小,那麼數據塊Hash的數量也得很小,這就意味着每個數據塊相對較大。大數據塊影響節點之間進行交易的效率,因爲只有當大數據塊全部下載下來並校驗通過後,才能與其他節點進行交易。

就解決上面兩個問題是用一個簡單的Merkle Tree代替Hash List。設計一個層數足夠多的滿二叉樹,葉節點是數據塊的Hash,不足的葉節點用0來代替。上層的節點是其對應孩子節點串聯的hash。Hash算法和普通torrent一樣採用SHA1。其數據傳輸過程和第一節中描述的類似。 
這裏寫圖片描述

可信計算

可信計算是可信計算組爲分佈式計算環境中參與節點的計算平臺提供端點可信性而提出的。可信計算技術在計算平臺的硬件層引入可信平臺模塊(Trusted Platform,TPM),實際上爲計算平臺提供了基於硬件的可信根(Root of trust,RoT)。從可信根出發,使用信任鏈傳遞機制,可信計算技術可對本地平臺的硬件及軟件實施逐層的完整性度量,並將度量結果可靠地保存再TPM的平臺配置寄存器(Platform configuration register,PCR)中,此後遠程計算平臺可通過遠程驗證機制(Remote Attestation)比對本地PCR中度量結果,從而驗證本地計算平臺的可信性。可信計算技術讓分佈式應用的參與節點擺脫了對中心服務器的依賴,而直接通過用戶機器上的TPM芯片來建立信任,使得創建擴展性更好、可靠性更高、可用性更強的安全分佈式應用成爲可能[10]。可信計算技術的核心機制是遠程驗證(remote attestation),分佈式應用的參與結點正是通過遠程驗證機制來建立互信,從而保障應用的安全。 
這裏寫圖片描述

文獻提出了一種基於Merkle Tree的遠程驗證機制,其核心是完整性度量值哈希樹。

首先,RAMT 在內核中維護的不再是一張完整性度量值列表(ML),而是一棵完整性度量值哈希樹(integrity measurement hash tree,簡稱IMHT).其中,IMHT的葉子結點存儲的數據對象是待驗證計算平臺上被度量的各種程序的完整性哈希值,而其內部結點則依據Merkle 哈希樹的構建規則由子結點的連接的哈希值動態生成。

其次,爲了維護IMHT 葉子結點的完整性,RAMT 需要使用TPM 中的一段存儲器來保存IMHT 可信根哈希的值。

再次,RAMT 的完整性驗證過程基於認證路徑(authentication path)實施.認證路徑是指IMHT 上從待驗證葉子結點到根哈希的路徑。

區塊鏈-簡單驗證支付

中本聰在他的創世論文中一個概念,就是SPV,中文意思是簡單支付驗證,從這裏我們可以看出SPV指的是“支付驗證”而不是“交易驗證”,那這兩者有什麼區別嗎?簡單的說就是支付驗證只需驗證該筆交易是否被確認過了,而交易驗證是需要驗證該筆交易是否滿足一些條件如“餘額”是否足夠,還有該筆交易有沒有存在雙花等等一些問題,只有一切都沒什麼問題後該筆交易纔算驗證通過,可以看出交易驗證要比支付驗證更加複雜,所以它一般是由挖礦節點來完成的,而支付驗證只要普通的輕錢包就可以完成。那現在有一個問題了,SPV是如何實現的?答案就是默克爾樹

假設我們要驗證區塊中存在Hash值爲9Dog:64(綠色框)的交易,我們僅需要知道1FXq:18、ec20、8f74(黃色框)即可計算出781a、5c71與Root節點(藕粉色框)的哈希,如果最終計算得到的Root節點哈希與區塊頭中記錄的哈希(6c0a)一致,即代表該交易在區塊中存在。這是因爲我上文提到的兩個點,一個是默克爾樹是從下往上逐層計算的,所以只要知道相鄰的另一個節點的hash值就可以一直往上計算直到根節點,另一個是根節點的hash值可以準確的作爲一組交易的唯一摘要,依據這兩點就可以來驗證一筆交易是否存在。
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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