簡單瞭解默克爾(Merkle)樹

       Merkle樹是Ralph Merkle在1988年發明的,旨在構建更好的數字簽名。原文是A DIGITAL SIGNATURE BASED ON A CONVENTIONAL ENCRYPTION FUNCTION本篇論文在Weki百科中顯示比較難以讀懂(對於非密碼學專業的人來說),第二篇參考是Providing Authentication and Integrity in Outsourced Databases using Merkle Hash Tree's,比較容易讀懂。當然兩篇文章我是在維基上找到的,只有幾行字來介紹提出Merkle tree的文獻。

       

一、先講解一下hash函數。

         哈希函數(Hash function),也被稱爲散列或雜湊函數。哈希函數是一個公開函數,主要的功能是將消息M映射成一個長度較短且固定的值H(M),是一個明文到密文的不可逆映射,只有加密而沒有解密過程。函數如下:

其中,value是一個定長的數值,作爲輸入value1和value2的哈希值。value的特點是,如果value1或者value2中有一個值發生了變化,那麼它的數值將會與原來完全不一致,而且這種不一致的變化是沒有任何規律可言的。同時,我們也不可能根據value的值反推出value1和value2的數值。哈希函數的特點保證了對於任意的兩個輸入組合,都有唯一的輸出數值與之對應,這個特性可以用於校驗輸入函數參數的性質。

        

 

原因:學習區塊鏈相關的內容的時候發現Merkle tree和hash不是很瞭解。

先講解一下hash的介紹:

無論輸入是什麼數字格式、文件有多大,輸出都是固定長度的比特串。以比特幣使用的Sh256算法爲例,無論輸入是什麼數據文件,輸出就是256bit

         哈希算法:“單向加密”,是指丟掉一部分信息的加密算法。

 

二、Merkle Tree

Merkle tree看起來像是二叉樹,是一個滿二叉樹(每一個層的結點數都達到最大值的二叉樹),一棵Merkle樹的結構如下:

紅色的是根結點,灰色的是非葉子結點,黃色的是葉子結點。葉子結點的數值是直接根據數據塊的值與0作爲參數,經過Hash運算得來的,而灰色結點的值是以兩個孩子結點的hash值作爲輸入,經過Hash運算得來的。一般的方法圖

一棵Merkle樹有如下特點:

  1. 葉子結點的值是實際數據塊的Hash值。
  2. 每個非葉子結點的值,都是孩子結點的Hash值。根結點稱爲Merkle根
  3. 如果樹是二叉樹的話,稱爲二叉Merkle樹,且二叉Merkle樹一定是滿二叉樹(奇數葉子湊成偶數個,如果出現需要處理的數據塊是奇數個,只需要把這些數據塊中的任意一個複製一份湊成偶數個就行,一般選擇複製最後一個塊。

很自然的,我們會想到一個問題,爲什麼使用Merkle樹,而不是直接把所有葉子結點經過一次Hash計算之後,直接給出結論?比如像上面的介紹圖中,共有16個葉子結點,那麼總共需要進行16Hash運算即可:

假設A將上面的Root發給下一個人B之後,A需要向B證明M6沒有被修改過,那麼需要將M6到M15的數據都發送給B,B則需要將這些數據重新進行Hash計算來驗證正確性,操作的複雜度是O(n),驗證的複雜度高,同時應該明白系統驗證的次數應該會遠遠高於計算的次數。

相反如果使用Merkle樹來進行記錄:

當需要驗證M6沒有被篡改過,A只需要將圖中標藍色的節點數據發給B就行,在二叉樹的情況下,它的計算複雜度僅僅是,其中m是數據塊的個數。

Merkle Tree的整體結構看上去如下圖:

Merkle樹大多用來進行完整性驗證,比如分佈式環境下,從多臺主機獲取數據,怎麼驗證獲取的數據是否正確呢,只要驗證Merkle樹根哈希一致,即可。例如,下圖中L3數據塊發生錯誤(比如數據被修改了),錯誤會傳導到計算hash(L3),接着傳導到計算hash(Hash1-0+Hash1-1),最後傳導到根哈希,導致根哈希的不一致,可以說,任何底層數據塊的變化,最終都會傳導到根哈希。另外如果根哈希不一致,也可以通過Merkle樹快速定位到導致不一致的數據。

Merkle樹還可以用來對數據進行快速比對,快速定位到不一致的數據。比如分佈式存儲中,一份數據會有多個副本,並且分佈在不同的機器上。爲了保持數據一致性,需要進行副本同步,而首要的就是比對當前副本是否一致,如一致,則無需同步,如不一致,還需找出不一致的地方,然後進行同步。很明顯,如果採用直接傳輸數據進行比對,非常低效,一般採用對數據進行哈希,傳輸哈希值進行對比的方法。爲此,可以對每臺機器需要比對的數據構造Merkle樹,如果根哈希一致,則數據相同,如果根哈希不一致,則通過Merkle樹快速檢索到不一致的數據。下面舉例說明快速檢索的過程,如上圖藍色標註所示。假設兩臺機器中L3數據塊不一致,我們對比根哈希,發現根哈希不一致,即,數據不一致,此時需要找出是那一塊不一致,分別對比Hash0Hash1,發現是Hash1不一致,接着向下發現是Hash1-0不一致,這樣就定位到是L3數據塊不一致。定位過程的算法複雜度爲O(log(n))

還有一種數據結構,在一定程度上可以看做是Merkle樹的子樹,但又不完全一樣,這個數據結構是Hash list(爲了避免中文哈希列表與哈希表的誤解,這裏使用英文名稱),我們下面看一下這個Hash list

三、Hash list

    在點對點網絡中數據傳輸的時候,爲了提高效率往往會同時從多個機器下載數據的不同部分,即,不是從一臺機器下載整個數據,而是將完整數據分成不同的部分,分別同時從不同的機器獲取完整數據的不同組成部分。這樣分塊傳輸不但可以同時從多臺機器下載數據,另一個好處是如果這一小塊數據傳輸過程中損壞了,只要重新下載這一小數據塊就可以了,不用重新下載整個數據。

但這種分佈式環境下,很多機器應該認爲是不穩定或者不可信的,如何校驗整個數據的完整性及每一小數據塊的完整性呢?

爲了校驗每一個數據塊,我們需要對每個數據塊做哈希,形成一個哈希列表,這樣進行下載前,我們先要獲取一個哈希列表,下載後,我們就能夠通過哈希列表,來驗證每一個數據塊。哪怎麼保證這個哈希列表是正確的呢,或者說怎麼校驗完整數據呢?只要每一個數據塊哈希是正確的,最終獲取的完整數據就一定是正確的,所以,我們需要對哈希列表進行哈希得到根哈希,將此根哈希放到一個可信源中,在下載數據前,先從可信數據源哪裏獲取到數據的跟哈希,然後從任意機器獲取哈希列表,再下載數據塊。這樣,數據完整性可以通過根哈希來保證。

 

以上都是來源於網絡,我只是將其整合了一下。更加容易方便的閱讀。

 

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