什么是哈希算法。
哈希算法,又稱散列算法,它是一個單向函數(shù),可以把任意長度的輸入數(shù)據(jù)轉(zhuǎn)化為固定長度的輸出:
h\=H(x)h=H(x)h\=H(x)
例如,對?morning?
和?bitcoin?
兩個輸入進(jìn)行某種哈希運(yùn)算,得到的結(jié)果是固定長度的數(shù)字:
H("morning") = c7c3169c21f1d92e9577871831d067c8
H("bitcoin") = cd5b1e4947e304476c788cd474fb579a
我們通常用十六進(jìn)制表示哈希輸出。
因?yàn)楣K惴ㄊ且粋€單向函數(shù),要設(shè)計(jì)一個安全的哈希算法,就必須滿足:通過輸入可以很容易地計(jì)算輸出,但是,反過來,通過輸出無法反推輸入,只能暴力窮舉。
H("???????") = c7c3169c21f1d92e9577871831d067c8
H("???????") = cd5b1e4947e304476c788cd474fb579a
想要根據(jù)上述結(jié)果反推輸入,只能由計(jì)算機(jī)暴力窮舉。
哈希碰撞
一個安全的哈希算法還需要滿足另一個條件:碰撞率低。
碰撞是指,如果兩個輸入數(shù)據(jù)不同,卻恰好計(jì)算出了相同的哈希值,那么我們說發(fā)生了碰撞:
H("data-123456") = a76b1fb579a02a476c789d9115d4b201 H("data-ABCDEF") = a76b1fb579a02a476c789d9115d4b201
因?yàn)檩斎霐?shù)據(jù)長度是不固定的,所以輸入數(shù)據(jù)是一個無限大的集合,而輸出數(shù)據(jù)長度是固定的,所以,輸出數(shù)據(jù)是一個有限的集合。把一個無限的集合中的每個元素映射到一個有限的集合,就必然存在某些不同的輸入得到了相同的輸出。
哈希碰撞的本質(zhì)是把無限的集合映射到有限的集合時必然會產(chǎn)生碰撞。我們需要計(jì)算的是碰撞的概率。很顯然,碰撞的概率和輸出的集合大小相關(guān)。輸出位數(shù)越多,輸出集合就越大,碰撞率就越低。
安全哈希算法還需要滿足一個條件,就是輸出無規(guī)律。輸入數(shù)據(jù)任意一個bit(某個字節(jié)的某一個二進(jìn)制位)的改動,會導(dǎo)致輸出完全不同,從而讓攻擊者無法逐步猜測輸入,只能依賴暴力窮舉來破解:
H("hello-1") = 970db54ab8a93b7173cb48f55e67fd2c
H("hello-2") = 8284353b768977f05ac600baad8d3d17
哈希算法有什么作用?
假設(shè)我們相信一個安全的哈希算法,那么我們認(rèn)為,如果兩個輸入的哈希相同,我們認(rèn)為兩個輸入是相同的。
如果輸入的內(nèi)容就是文件內(nèi)容,而兩個文件的哈希相同,說明文件沒有被修改過。當(dāng)我們從網(wǎng)站上下載一個非常大的文件時,我們?nèi)绾未_定下載到本地的文件和官方網(wǎng)站發(fā)布的原始文件是完全相同,沒有經(jīng)過修改的呢?哈希算法就體現(xiàn)出了作用:我們只需要計(jì)算下載到本地的文件哈希,再和官方網(wǎng)站給出的哈希對比,如果一致,說明下載文件是正確的,沒有經(jīng)過篡改,如果不一致,則說明下載的文件肯定被篡改過。
大多數(shù)軟件的官方下載頁面會同時給出該文件的哈希值,以便讓用戶下載后驗(yàn)證文件是否被篡改:
和文件類似,如果兩份數(shù)據(jù)的哈希相同,則可以100%肯定,兩份數(shù)據(jù)是相同的。比特幣使用哈希算法來保證所有交易不可修改,就是計(jì)算并記錄交易的哈希,如果交易被篡改,那么哈希驗(yàn)證將無法通過,說明這個區(qū)塊是無效的。
常用哈希算法
常用的哈希算法以及它們的輸出長度如下:
哈希算法 | 輸出長度(bit) | 輸出長度(字節(jié)) |
---|---|---|
MD5 | 128 bit | 16 bytes |
RipeMD160 | 160 bits | 20 bytes |
SHA-1 | 160 bits | 20 bytes |
SHA-256 | 256 bits | 32 bytes |
SHA-512 | 512 bits | 64 bytes |
比特幣使用的哈希算法有兩種:SHA-256? 和? ?RipeMD160
SHA-256的理論碰撞概率是:嘗試2的130次方的隨機(jī)輸入,有99.8%的概率碰撞。注意2130是一個非常大的數(shù)字,大約是1361萬億億億億。以現(xiàn)有的計(jì)算機(jī)的計(jì)算能力,是不可能在短期內(nèi)破解的。
比特幣使用兩種哈希算法,一種是對數(shù)據(jù)進(jìn)行兩次SHA-256計(jì)算,這種算法在比特幣協(xié)議中通常被稱為hash256或者dhash。
另一種算法是先計(jì)算SHA-256,再計(jì)算RipeMD160,這種算法在比特幣協(xié)議中通常被稱為hash160。
const
bitcoin = require('bitcoinjs-lib'),
createHash = require('create-hash');
Run
運(yùn)行上述代碼,觀察對一個字符串進(jìn)行SHA-256、RipeMD160、hash256和hash160的結(jié)果。
區(qū)塊鏈不可篡改特性
- 有了哈希算法的預(yù)備知識,我們來看比特幣的區(qū)塊鏈如何使用哈希算法來防止交易記錄被篡改。
- 區(qū)塊本身記錄的主要數(shù)據(jù)就是一系列交易,所以,區(qū)塊鏈?zhǔn)紫纫WC任何交易數(shù)據(jù)都不可修改。
Merkle Hash
在區(qū)塊的頭部,有一個Merkle Hash字段,它記錄了本區(qū)塊所有交易的Merkle Hash:
Merkle Hash是把一系列數(shù)據(jù)的哈希根據(jù)一個簡單算法變成一個匯總的哈希。
假設(shè)一個區(qū)塊有4個交易,我們對每個交易數(shù)據(jù)做dhash,得到4個哈希值a1
,a2
,a3
和a4
:
a1 = dhash(tx1)
a2 = dhash(tx2)
a3 = dhash(tx3)
a4 = dhash(tx4)
注意到哈希值也可以看做數(shù)據(jù),所以可以把a1
和a2
拼起來,a3
和a4
拼起來,再計(jì)算出兩個哈希值b1
和b2
:
┌───────────────┐ ┌───────────────┐
│b1=dhash(a1+a2)│ │b2=dhash(a3+a4)│
└───────────────┘ └───────────────┘
▲ ▲
┌───────┴───────┐ ┌───────┴───────┐
│ │ │ │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│a1=dhash(tx1)│ │a2=dhash(tx2)│ │a3=dhash(tx3)│ │a4=dhash(tx4)│
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
最后,把b1
和b2
這兩個哈希值拼起來,計(jì)算出最終的哈希值,這個哈希就是Merkle Hash:
┌───────────────────┐
│merkle=dhash(b1+b2)│
└───────────────────┘
▲
┌───────────────┴───────────────┐
│ │
┌───────────────┐ ┌───────────────┐
│b1=dhash(a1+a2)│ │b2=dhash(a3+a4)│
└───────────────┘ └───────────────┘
▲ ▲
┌───────┴───────┐ ┌───────┴───────┐
│ │ │ │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│a1=dhash(tx1)│ │a2=dhash(tx2)│ │a3=dhash(tx3)│ │a4=dhash(tx4)│
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
如果交易的數(shù)量不恰好是4個怎么辦?
????????例如,只有3個交易時,第一個和第二個交易的哈希a1
和a2
可以拼起來算出b1
,第三個交易只能算出一個哈希a3
,這個時候,就把a(bǔ)3直接復(fù)制一份,算出b2
,這樣,我們也能最終計(jì)算出Merkle Hash:
┌───────────────────┐
│merkle=dhash(b1+b2)│
└───────────────────┘
▲
┌───────────────┴───────────────┐
│ │
┌───────────────┐ ┌───────────────┐
│b1=dhash(a1+a2)│ │b2=dhash(a3+a3)│
└───────────────┘ └───────────────┘
▲ ▲
┌───────┴───────┐ ┌───────┴───────┐
│ │ │ │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌ ─ ─ ─ ─ ─ ─ ┐
│a1=dhash(tx1)│ │a2=dhash(tx2)│ │a3=dhash(tx3)│
└─────────────┘ └─────────────┘ └─────────────┘ └ ─ ─ ─ ─ ─ ─ ┘
????????如果有5個交易,我們可以看到,a5
被復(fù)制了一份,以便計(jì)算出b3
,隨后b3
也被復(fù)制了一份,以便計(jì)算出c2
。總之,在每一層計(jì)算中,如果有單數(shù),就把最后一份數(shù)據(jù)復(fù)制,最后一定能計(jì)算出Merkle Hash:
┌─────────┐
│ merkle │
└─────────┘
▲
┌───────────┴───────────┐
│ │
┌───┐ ┌───┐
│c1 │ │c2 │
└───┘ └───┘
▲ ▲
┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │
┌───┐ ┌───┐ ┌───┐ ┌ ─ ┐
│b1 │ │b2 │ │b3 │ b3
└───┘ └───┘ └───┘ └ ─ ┘
▲ ▲ ▲
┌──┴──┐ ┌──┴──┐ ┌──┴──┐
│ │ │ │ │ │
┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌ ─ ┐
│a1 │ │a2 │ │a3 │ │a4 │ │a5 │ a5
└───┘ └───┘ └───┘ └───┘ └───┘ └ ─ ┘
從Merkle Hash的計(jì)算方法可以得出結(jié)論:修改任意一個交易哪怕一個字節(jié),或者交換兩個交易的順序,都會導(dǎo)致Merkle Hash驗(yàn)證失敗,也就會導(dǎo)致這個區(qū)塊本身是無效的,所以,Merkle Hash記錄在區(qū)塊頭部,它的作用就是保證交易記錄永遠(yuǎn)無法修改。
Block Hash
區(qū)塊本身用Block Hash——也就是區(qū)塊哈希來標(biāo)識。但是,一個區(qū)塊自己的區(qū)塊哈希并沒有記錄在區(qū)塊頭部,而是通過計(jì)算區(qū)塊頭部的哈希得到的:
區(qū)塊頭部的Prev Hash記錄了上一個區(qū)塊的Block Hash,這樣,可以通過Prev Hash追蹤到上一個區(qū)塊。
由于下一個區(qū)塊的Prev Hash又會指向當(dāng)前區(qū)塊,這樣,每個區(qū)塊的Prev Hash都指向自己的上一個區(qū)塊,這些區(qū)塊串起來就形成了區(qū)塊鏈。
區(qū)塊鏈的第一個區(qū)塊(又稱創(chuàng)世區(qū)塊)并沒有上一個區(qū)塊,因此,它的Prev Hash被設(shè)置為00000000...000
。
如果一個惡意的攻擊者修改了一個區(qū)塊中的某個交易,那么Merkle Hash驗(yàn)證就不會通過。所以,他只能重新計(jì)算Merkle Hash,然后把區(qū)塊頭的Merkle Hash也修改了。這時,我們就會發(fā)現(xiàn),這個區(qū)塊本身的Block Hash就變了,所以,下一個區(qū)塊指向它的鏈接就斷掉了。
由于比特幣區(qū)塊的哈希必須滿足一個難度值,因此,攻擊者必須先重新計(jì)算這個區(qū)塊的Block Hash,然后,再把后續(xù)所有區(qū)塊全部重新計(jì)算并且偽造出來,才能夠修改整個區(qū)塊鏈。
在后面的挖礦中,我們會看到,修改一個區(qū)塊的成本就已經(jīng)非常非常高了,要修改后續(xù)所有區(qū)塊,這個攻擊者必須掌握全網(wǎng)51%以上的算力才行,所以,修改區(qū)塊鏈的難度是非常非常大的,并且,由于正常的區(qū)塊鏈在不斷增長,同樣一個區(qū)塊,修改它的難度會隨著時間的推移而不斷增加。
小結(jié)
區(qū)塊鏈依靠安全的哈希算法保證所有區(qū)塊數(shù)據(jù)不可更改;
交易數(shù)據(jù)依靠Merkle Hash確保無法修改,整個區(qū)塊依靠Block Hash確保區(qū)塊無法修改;文章來源:http://www.zghlxwxcb.cn/news/detail-459396.html
工作量證明機(jī)制(挖礦)保證修改區(qū)塊鏈的難度非常巨大從而無法實(shí)現(xiàn)。文章來源地址http://www.zghlxwxcb.cn/news/detail-459396.html
到了這里,關(guān)于區(qū)塊鏈中的:哈希算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!