IPFS-文件HASH值計算

IPFS如何計算文件hash?

IPFS採用了SHA2-256這個安全級別還算高的算法,對任意長度的內容,生成的HASH值長度固定,都是32個字節。

在Linux下,直接用sha256sum可以計算SHA2-256格式的HASH值:

[root@VM_0_14_centos bin]# sha256sum ipfsfile.txt 
e150a1ec81e8e93e1eae2c3a77e66ec6dbd6a3b460f89c1d08aecf422ee401a0  ipfsfile.txt
[root@VM_0_14_centos bin]# ./ipfs add ipfsfile.txt
added QmQU2gS4gZ7TpiTECjDUxdQFd9bBBEWxDxPPfhLfYHVuei ipfsfile.txt
 7 B / ? [---------------------------------------------------------------------------------=------] [root@VM_0_14_centos bin]#

得到的結果有64字節,其原因是因爲用了十六進制的表示方式,每個字符表示4個bit,加在一起就是256bit,也就是32字節。

在IPFS中,並不能利用上面得到的SHA2-256結果,去確定文件地址,因爲IPFS還有一些額外的因素需要考慮。
我們把 ipfsfile.txt 加入到IPFS中,除了正文裏面的 123456 幾個字符之外,IPFS還會添加一些元數據。
通過如下命令我們可以看到IPFSF裏面到底存放了什麼內容:

[root@VM_0_14_centos bin]# ./ipfs object get QmQU2gS4gZ7TpiTECjDUxdQFd9bBBEWxDxPPfhLfYHVuei
{"Links":[],"Data":"\u0008\u0002\u0012\u0007123456\n\u0018\u0007"}
[root@VM_0_14_centos bin]# 

返回的是一個JSON格式的字符串,Data顯示了具體的內容。可見在文件的原始內容之外,添加了一些其他的數據。** IPFS會把文件數據以unixfs這種格式保存,可以認爲,它是IPFS的核心數據結構MerkleDAG的一個表現方式。 **

我們可以通過獲取IPFS的原始格式的數據,來計算正確的HASH值。IPFS保存的內容會被分成許多塊(block),本例的文件因爲比較小,一個塊就可以保存。
所以,我們可以用如下的命令直接獲取IPFS block的內容:

[root@VM_0_14_centos bin]# ./ipfs block get QmQU2gS4gZ7TpiTECjDUxdQFd9bBBEWxDxPPfhLfYHVuei | sha256sum
1f9b484934c481946f11af0d87f8c04603fa8bfa6b8589185edf506c1e1cb09b  -
[root@VM_0_14_centos bin]# 

該block的HASH值用十六進制數表示爲:1f9b484934c481946f11af0d87f8c04603fa8bfa6b8589185edf506c1e1cb09b 。它也就是IPFS用特定格式保存文件之後的HASH值。

是否用該HASH值就能得到我們通常看到的IPFS文件的HASH值?好像不是那麼回事,因爲我們看到的文件HASH值都是以Qm開頭的,顯然在這裏對不上號。這就涉及到另外一個話題——動態選擇HASH算法的設計。

IPFS-Multihash

【推薦】官方:https://github.com/multiformats/multihash

雖然現在SHA2-256還比較安全,但隨着科技的發展,說不定哪天就突然有人宣佈,可以破解它呢?那自然需要採用更先進的算法。但IPFS的協議制定好了,也不能隨便改。怎麼辦呢?雖然現在用的是SHA2-256,但可以宣稱我支持多種HASH算法,到時候升級算法即可,但不會有大的架構改動。

於是,IPFS採用了multihash這種簡單的HASH表示方式,支持多種HASH算法。如果未來修改算法,用的仍然是multihash,保證了表達方式的持續性。

multihash是一種自識別hash (Self identifying hashes)

multihash 多重哈希 遵循TLV 模式(type-length-value)。它其實就是一個字符串,由三部分組成:HASH算法編碼、HASH值的長度(字節數)、HASH 值。

SHA2-256的編碼爲0x12,其HASH摘要長度爲32字節(十六進制數爲0x20)。把1220加到前面所得HASH值的開頭,我們得到本例文件的multihash編碼(十六機制):

12201f9b484934c481946f11af0d87f8c04603fa8bfa6b8589185edf506c1e1cb09b

官方sha-256 格式demo:
在這裏插入圖片描述總結:我們把 ipfsfile.txt 加入到IPFS中,除了正文裏面的 xxx 幾個字符之外,IPFS還會添加一些元數據。然後對這個添加元數據的文件進行了sha256sum,然後再multihash 規則(前面加1120),文件的multihash編碼(十六機制)。

易用需求:Base58

【推薦】官網:https://github.com/keis/base58

但這個HASH值顯然也不是我們看到的內容。那是怎麼回事呢?它太長了,一堆數字讀起來也不容易,所以需要再進行編碼,壓縮其長度,且容易被傳播。爲此,IPFS採用了Base58這種編碼。

Base58最早被比特幣採用,如今在區塊鏈項目中非常流行,經常用於表示錢包地址。做過開發的朋友可能比較瞭解Base64這種編碼,能把任意二進制內容轉換成方便軟件查看的可讀字符。

但Base64有一些缺點,就是某些字符不和諧,比如,O和0容易混淆,+和/等符號,很容易讓人把一個完整的字符串認爲是兩個不同的字符串,形成閱讀上的障礙。有時候我們用鼠標一點,想自動選中整個字符串,卻因爲這些符號的干擾,導致選擇操作沒有那麼高效。因此,就誕生了Base58這種編碼。

設計Base58主要的目的是:

  • 避免混淆。在某些字體下,數字0和字母大寫O,以及字母大寫I和字母小寫l會非常相似。
  • 不使用"+“和”/"的原因是非字母或數字的字符串作爲帳號較難被接受。
  • 沒有標點符號,通常不會被從中間分行。
  • 大部分的軟件支持雙擊選擇整個字符串。

Base58的代碼非常簡單,查看官網https://github.com/keis/base58

python安裝模塊 base58 進行驗證

pip install base58

[root@VM_0_14_centos ~]# python
Python 2.7.5 (default, Aug  7 2019, 00:51:29) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import base58
>>> base58.b58encode_int(int("12201f9b484934c481946f11af0d87f8c04603fa8bfa6b8589185edf506c1e1cb09b", 16))
'QmQU2gS4gZ7TpiTECjDUxdQFd9bBBEWxDxPPfhLfYHVuei'
>>> 

基於前面生成的multihash 編碼(12201f9b484934c481946f11af0d87f8c04603fa8bfa6b8589185edf506c1)進行計算,得到的結果
QmQU2gS4gZ7TpiTECjDUxdQFd9bBBEWxDxPPfhLfYHVuei 正是前面我們用ipfs add命令得到的HASH值!

注意: IPFS現在的multihash值,都是以1220開頭的,按照Base58的算法,算出來的結果就都是以Qm開頭。

總結:我們把 ipfsfile.txt 加入到IPFS中,除了正文裏面的 xxx 幾個字符之外,IPFS還會添加一些元數據,形成IPFS文件。然後對這個添加元數據的文件進行了sha256sum,然後再multihash 規則(前面加1120),文件的multihash編碼(十六機制)。因爲這個不好記憶識別,它又用 base58對我們的 multihash 生成最終的IPFS文件的HASH值。

簡化總結爲:原始數據添加元數據封裝成IPFS文件 -> 計算SHA2-256 -> 封裝成multihash -> 轉換成Base58

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