摘要:當然,高飛幣有一個致命安全隱患,假設愛麗絲通過把她簽署的聲明發(fā)送給鮑勃,即將她的幣轉(zhuǎn)給鮑勃,但并沒有告訴其他人,此時她也可以創(chuàng)建另一個簽名,聲明將同樣一只幣轉(zhuǎn)給了查克,對于查克來說,這看起來是一個完全有效的交易。...
歡迎來到四葉草堂,我是龍笑生。數(shù)字簽名(digital signatures)理論和哈希函數(shù)一起,為加密貨幣奠定了基礎。更多精彩內(nèi)容,敬請關注“四葉草堂”,今天繼續(xù)分享《區(qū)塊鏈:技術(shù)驅(qū)動金融》一書的精彩部分。
所有貨幣都需要通過某種方式控制供給,并需要實施各種安全屬性以防止欺騙行為發(fā)生,就法定貨幣而言,中央銀行這樣的機構(gòu)控制貨幣供給,并在實體貨幣上加上防偽標識,這些安全屬性提升了攻擊貨幣的門檻和難度,但并非不可能偽造,最終,執(zhí)法部門仍需要介入,以防止貨幣系統(tǒng)規(guī)則受到破壞。加密數(shù)字貨幣也必須采取安全措施,以防御破壞系統(tǒng)狀態(tài)的行為,同時加密數(shù)字貨幣還需要防止“混淆”,即對不同的人說出相互矛盾的話。例如,如果愛麗絲讓鮑勃確信她向他支付了一個數(shù)字幣,她就不能再說服卡羅爾,也給她支付同一個數(shù)字幣。加密數(shù)字貨幣與法定貨幣的不同在于,其安全規(guī)則需要完全通過技術(shù)手段實現(xiàn),而非依賴于中央機構(gòu)。
哈希函數(shù)是一個數(shù)學函數(shù),具有以下三個特性:● 其輸入可為任意大小的字符串?!?它產(chǎn)生固定大小的輸出,例如輸出值大小為256位?!?它能進行有效計算,簡單來說就是對于特定的輸入字符串,在合理時間內(nèi),可以算出哈希函數(shù)的輸出。此外,哈希函數(shù)達到密碼安全,還需要具有以下三個附加特性:(1)碰撞阻力(collision-resistance);(2)隱秘性(hiding);(3)謎題友好(puzzle-friendliness)。
哈希函數(shù)的第一個特性是它要具有碰撞阻力,這里的碰撞指對于兩個不同的輸入,產(chǎn)生相同的輸出。如果對于哈希函數(shù)H(·),沒有人能夠以較短時間找到碰撞,我們則稱該函數(shù)具有碰撞阻力。對于一個256位輸出的哈希函數(shù)來說,最壞的情況是你需要進行2256+1次哈希函數(shù)計算,平均次數(shù)為2128次,這簡直是一個天文數(shù)字——如果一臺電腦每秒計算10000個哈希值,計算2128個哈希值,需要花1027多年時間!為此,我們可以將哈希輸出作為信息摘要(message digest)。以SecureBox為例,SecureBox是一個允許用戶上傳文件,并保證文件被完整下載的線上文件存儲系統(tǒng),假設愛麗絲上傳了很大的文件,并希望能夠在之后下載時確認下載的文件與她上傳的文件相同。無碰撞哈希函數(shù)為這個問題提供了簡單有效的解決方法,愛麗絲只需要記住原文件的哈希值,從SecureBox下載文件后,可以計算下載文件的哈希值,并與原文件哈希值進行對比,如果哈希值相同,那么愛麗絲可以說該文件就是她上傳的那一個,但是如果不同,她則可以確定文件被破壞了。
哈希函數(shù)擁有的第二個特性是其隱秘性。隱秘性保證,如果我們僅僅知道哈希函數(shù)的輸出y=H(x),我們沒有可行的辦法算出輸入值x。在類似拋硬幣的“正面”、“反面”實驗中,如果輸入值并非來自分散的集合,我們是否還能得到隱秘性?幸運的是,對于這個問題答案是肯定的!我們可以通過與另一個較為分散的輸入進行結(jié)合,而將一個并不分散的輸入進行隱秘。承諾方案就是應用了這一原理,我們首先產(chǎn)生一個臨時隨機數(shù)。然后將這個臨時隨機數(shù)與承諾信息msg一起代入承諾函數(shù),計算承諾函數(shù)輸出值com,然后公布該輸出,這個過程就如同將封好的信封放到一個人人能看到的桌上那樣。之后,我們公布用于產(chǎn)生承諾的臨時隨機數(shù),并公布信息msg,此時任何人都可以驗證這時公布的msg是否與之前的承諾信息一致,這個階段就如同打開信封。
哈希函數(shù)的第三個安全特性為謎題友好特性。直覺上,謎題友好可以這樣解釋,如果有一個人想找到y(tǒng)值所對應的輸入,假定在輸入集合中,有一部分是非常隨機的,那么他將非常難以求得y值對應的輸入。這個直覺是:如果H有一個n位輸出,那么它的可能取值有2n個。解決這個謎題要求找到一個位于集合Y(通常比所有輸出值集合小很多)內(nèi)的輸出值,Y的大小決定了謎題的難度,如果Y是所有n位字符串的集合,這個謎題就毫無意義,然而,如果Y只有一個元素,那么這個謎題難度最大。如果一個哈希函數(shù)具備謎題友好特性,這就意味著對于這個謎題沒有一個解決策略,比只是隨機地嘗試x取值會更好。
哈希指針是一種數(shù)據(jù)結(jié)構(gòu),簡單來說,哈希指針是一個指向數(shù)據(jù)存儲位置及其位置數(shù)據(jù)哈希值的指針。一個普通的指針可以告訴你數(shù)據(jù)存儲的位置,哈希指針不但可以告訴你數(shù)據(jù)存儲的位置,并且還可以給你一種方式,讓你驗證數(shù)據(jù)沒有被篡改過。如果對手修改了區(qū)塊鏈中任意部位的數(shù)據(jù),那么將會導致下一個數(shù)據(jù)塊的哈希指針不正確,如果我們鎖定區(qū)塊鏈的頭部數(shù)據(jù),那么即使對手修改了所有哈希指針使其與修改過的數(shù)據(jù)一致,他也無法修改頭部數(shù)據(jù),從而我們就可以檢測到篡改行為。這樣做的結(jié)果是,如果對手想要篡改區(qū)塊鏈中任意地方的數(shù)據(jù),而且保證整個內(nèi)容一致,他需要篡改所有的哈希指針直至最開始的地方,最終將碰到障礙,因為他不能篡改鏈表頭部的指針,因此,我們可以搭建一個包含很多區(qū)塊的區(qū)塊鏈網(wǎng)絡,鏈表頭部的哈希指針被稱作創(chuàng)世區(qū)塊(genesis block)。
另一個我們可以用哈希指針建立的數(shù)據(jù)結(jié)構(gòu)是二叉樹。使用哈希指針的二叉樹也叫作梅克爾樹(Merkle trees),以其發(fā)明者拉爾夫·梅克爾的名字命名。在梅克爾樹的數(shù)據(jù)結(jié)構(gòu)中,所有的數(shù)據(jù)區(qū)塊都被兩兩分組,指向這些數(shù)據(jù)區(qū)塊的指針被存儲在上一層的父節(jié)點(parent node)中,而這些父節(jié)點再次被兩兩分組,并且指向父節(jié)點的指針被存儲在上一層的父節(jié)點中,一直持續(xù)這個過程,直到最后我們到達樹的根節(jié)點。與我們之前建立的區(qū)塊鏈不同,梅克爾樹的另一個特點是它可以實現(xiàn)簡潔的隸屬證明,假設某人想要證明某個數(shù)據(jù)區(qū)塊隸屬于梅克爾樹,我們只要記住樹根節(jié)點,然后他展示給我們數(shù)據(jù)塊信息,以及從該數(shù)據(jù)區(qū)塊通向樹根節(jié)點的那些區(qū)塊,我們可以忽略樹的其余部分,這樣做是因為這些區(qū)塊已經(jīng)足夠讓我們驗證通往樹根節(jié)點過程中所有的哈希值。
數(shù)字簽名(digital signatures)是密碼學中的第二個重要部分,該理論和哈希函數(shù)一起,為加密貨幣奠定了基礎。我們對數(shù)字簽名有兩個特性要求,使其與我們對手寫簽名的預期一致,第一,只有你可以制作你自己的簽名,但任何看到它的人都可以驗證其有效性;第二,我們希望簽名只與某一特定文件發(fā)生聯(lián)系,因此該簽名不能用于表明你支持另一份不同的文件。對于手寫簽名來說,第二條就如同確保別人不能將你的簽名從一份文件上剪下來,貼到另一份文件的末尾那樣。數(shù)字簽名方案由三個算法構(gòu)成:● (sk, pk) :=generateKeys(keysize), generateKeys方法把keysize作為輸入,來產(chǎn)生一對公鑰和私鑰。私鑰sk被安全保存,并用來簽名一段消息;公鑰pk是人人都可以看到的,拿到它就可以用來驗證你的簽名?!?sig:=sign(sk, message) ,簽名過程是把一段消息和私鑰作為一個輸入,輸出信息就是簽名。● isValid:=verify(pk, message, sig) ,驗證過程是通過把一段消息和簽名信息與公鑰作為輸入,如果返回的結(jié)果是真,證明簽名屬實;如果返回的結(jié)果為假,證明簽名消息為假。
要將算法概念轉(zhuǎn)化為現(xiàn)實中可執(zhí)行的數(shù)字簽名機制,我們還需要考慮許多實際問題,例如,很多簽名算法是隨機的(特別是比特幣使用的算法),因此我們需要隨機性的良好來源,不良隨機性會使你認為安全的算法變得不安全。另一個實際問題是關于信息大小,在實踐中,你能夠簽署的信息大小是有限制的,有一個簡單的方法可以解決這個限制:對信息的哈希值進行簽署,而非對信息本身進行簽署。如果使用輸出值為256位的加密哈希函數(shù),那么我們可以有效地簽署任何長度的信息。我們可以將信息的哈希值作為信息摘要,哈希函數(shù)具有碰撞阻力,因此這種方式是安全的,如果你簽署了哈希指針,那么該簽名覆蓋(或者說保護)整個結(jié)構(gòu)——這不僅僅是哈希指針本身,還包括哈希指針指向的整個區(qū)塊鏈,比如,如果簽署了區(qū)塊鏈末尾的哈希指針,其結(jié)果就是你有效地數(shù)字簽署了整條區(qū)塊鏈。
與數(shù)字簽名并行的一個有用技巧,是從數(shù)字簽名模式中拿出一個公共驗證密鑰,并將其與一個人的身份對等。如果你見到一條消息的簽名被公鑰pk正確驗證,那么你可以認為公鑰就是代表某一個參與者,從這個角度來說,公鑰就是身份。將公鑰視為身份的一個結(jié)果是,你可以隨時制定新的身份——可以簡單通過數(shù)字簽名方案中的generateKeys程序,生成新的密鑰對sk和pk,pk是你可以使用的新的公共身份,sk是相應的密鑰。你可以不經(jīng)過中央機構(gòu)而生成一個身份的概念可能看起來有悖常理,畢竟,如果有人剛好就生成了跟你一樣的密鑰,他不就能偷走你的比特幣嗎?我們的回答是,別人生成一個與你的256位密鑰相同的概率如此之小,在實踐中,我們不需要擔心它會發(fā)生。
高飛幣的規(guī)則是:● 高飛可以通過簽署聲明表示他使用唯一的貨幣編號來創(chuàng)建一個新幣?!?幣的所有人可以通過簽署聲明表示“將這個幣轉(zhuǎn)給X”(其中X為公鑰),將其轉(zhuǎn)給另一個人?!?任何人都可以驗證一只幣的有效性,跟隨哈希指針追溯到它是由高飛創(chuàng)建,并驗證過程中所有簽名。當然,高飛幣有一個致命安全隱患,假設愛麗絲通過把她簽署的聲明發(fā)送給鮑勃,即將她的幣轉(zhuǎn)給鮑勃,但并沒有告訴其他人,此時她也可以創(chuàng)建另一個簽名,聲明將同樣一只幣轉(zhuǎn)給了查克,對于查克來說,這看起來是一個完全有效的交易。鮑勃和查克似乎都可以有效表示自己是那個幣的所有人,這個就是所謂的雙重支付(double spending)——愛麗絲將同樣一只幣花了兩次。我們知道貨幣是不能這樣花的,事實上,雙重支付是任何加密貨幣需要解決的主要問題之一,高飛幣沒有解決這一問題,因此不安全。高飛幣很簡單,其貨幣轉(zhuǎn)移機制其實與比特幣非常相似,但是因為它并不安全,因此并不適合作為加密貨幣。
為解決雙重支付問題,我們設計另外一個加密貨幣——財奴幣(ScroogeCoin),財奴幣是以高飛幣為基礎創(chuàng)建的,但在數(shù)據(jù)結(jié)構(gòu)方面更復雜。一個叫財奴的指定實體將負責公布包含所有發(fā)生過的交易歷史記錄的僅增賬目(append-only ledger),賬目的僅增特性保證了寫入這個賬目的任何數(shù)據(jù)都會永久保留下來,為執(zhí)行這個僅增功能,財奴建立一個區(qū)塊鏈,并對區(qū)塊鏈進行數(shù)字簽名,因此就形成了一系列數(shù)據(jù)塊,每個數(shù)據(jù)塊都包含交易ID、交易內(nèi)容,以及上一個區(qū)塊的哈希指針,財奴數(shù)字簽名是針對最后一個哈希指針(它約束整個結(jié)構(gòu)中所有的數(shù)據(jù)),并將簽名與區(qū)塊鏈一起發(fā)布。現(xiàn)在,我們來看一下財奴幣的核心問題,財奴幣的工作原理是人們可以看見哪些幣是有效的。它可以防止雙重支付,因為每個人都可以查看區(qū)塊鏈,看到所有交易是否有效,每一只幣確實是只被消耗了一次,但其問題是財奴的權(quán)利太大了。財奴雖然不能創(chuàng)建虛假交易,因為他無法偽造其他人的簽名,但是他可以停止支持其他用戶的交易,不為他們提供服務并讓他們的貨幣無處可花。為了改善財奴幣,并建立一個可行系統(tǒng),需要解決的主要技術(shù)問題是:我們是否能讓系統(tǒng)“去財奴化”?也就是說,我們能否放棄中心化的財奴人物?我們能夠有一個在很多方面像財奴幣一樣運作的加密貨幣,但沒有中央信任機構(gòu)嗎?為回答這些問題,我們需要解決所有用戶如何在交易歷史記錄發(fā)生后,一致同意采用一個公開區(qū)塊鏈,他們必須一致同意哪些交易有效、哪些交易是實際發(fā)生了,最后,新幣的鑄造也需要通過去中心化的方式進行掌控。如果可以解決所有這些問題,那么我們就創(chuàng)建了一個如同財奴幣那樣的貨幣,但是沒有中心化的機構(gòu)管理,這樣的一個系統(tǒng)就與比特幣非常相像了。