非對稱加密,散列(哈希)算法

〇、序言

貨幣由於其天然屬性決定了其與安全不可分割的聯繫,從最早的金庫、保險櫃、鏢局到後來的ATM機、運鈔車;從存摺到銀行卡,從口令卡到優盾,安全技術的進步一步步推動着金融防護領域的更新。

傳統的貨幣的安全需求,密碼學是安全手段,是從“可用”到“安心用”的升級。而對比特幣來說,密碼學本身就是比特幣體系的一部分,沒有密碼學支撐的比特幣體系會完全崩塌,徹底“不可用”。本質上來說,比特幣和密碼學是融爲一體的,比特幣是自帶安全屬性的數字貨幣。因此,對比特幣用戶來說,瞭解比特幣背後的密碼學理論,有助於更好的理解比特幣;同時,通過密碼學理論的分享,也可以順便感受一下人類智慧的偉大。畢竟,在我眼裏,密碼學理論是大量聰慧的頭腦審慎思考的結果,精緻而又巧妙之處比比皆是。

一、密碼學理論

比特幣本身並沒有創造新的密碼學成果,但比特幣利用現有密碼學成果構建了一個令人驚奇的全新的數字貨幣世界:去中心化、區塊鏈、可編程貨幣等成果即使拋開比特幣本身而言也是值得讚賞的洞見。

首先,現代密碼學理論的共識遵循“柯克霍夫原則”:

柯克霍夫原則由奧古斯特·柯克霍夫在19世紀提出:密碼系統應該就算被所有人知道系統的運作步驟,仍然是安全的。

這個是什麼意思呢,拿鑰匙和鎖的例子來說,研製和生產鎖具(包括鑰匙)的工藝是完全公開的,鎖具被攻破只有兩種可能:一是證明工藝有漏洞,不需要拿到原裝鑰匙也能打開。二是窮盡各種鑰匙可能,在可接受的時間裏能夠從概率意義上試出來(暴力破解)。

算法是公開的,唯一需要保護的是密鑰,這是我們下文討論的基礎。

1.非對稱加密

先看對稱加密很好理解也符合直覺:

對稱加密:對同一份敏感數據,加密解密密鑰是相同的。

非對稱加密呢:

非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。因爲加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。 非對稱加密算法實現機密信息交換的基本過程是:甲方生成一對密鑰並將其中的一把作爲公用密鑰向其它方公開;得到該公用密鑰的乙方使用該密鑰對機密信息進行加密後再發送給甲方;甲方再用自己保存的另一把專用密鑰對加密後的信息進行解密。

我們用一幅圖來說明:

在上文的非對稱加密部分,密鑰A就是公開密鑰(簡稱公鑰),密鑰B就是私有密鑰(簡稱私鑰)。道理都懂,問題有意思在什麼地方呢?非對稱加密方式下密鑰A和密鑰B是怎麼找到的以及怎麼實現的?我們舉例說明:

假設我們現在已經找到了(具體怎麼找的後面會講)公鑰(3233,17)和私鑰(3233, 2753)。

注意,公鑰和私鑰不一定只有一個數字,是可以有多個的,具體幾個數字依賴於非對稱加密算法。

假設現在明文待加密信息是數字65,我們首先給出加密公式:

解釋一下,c代表加密後數字,(n,e)對應我們的公鑰對,m代表明文,≡的意思是同模運算,比如60≡4(mod 7),60對4取模後等於4。好了我們開始計算密文:

密文是2790,如何解密呢,解密公式:

d對應私鑰的2753,其餘字母和加密過程相同,於是解密運算爲:

我們得到了原來的明文數據65,這個例子可以看到加密和解密數據是不同的。

以上我們舉例使用的算法是大名鼎鼎的地球主流非對稱加密算法RSA,有關RSA的介紹參考阮一峯老師的文章。實際上我上面用到的數字也出自該文,實在是時間有限無法深入講解RSA的細節大家可以自行學習。比特幣體系實際使用的非對稱算法是橢圓曲線加密(ECC),可以到這裏詳細瞭解。

從上面的例子我們知道滿足非對稱加密的密鑰對是存在的,同時我們也做了加解密嘗試。實際上,非對稱加密算法的核心依賴於特定的數學難題,比如上文的RSA依賴於大數分解難題,如果該難題被破解了,算法本身也就被攻破了。另外,我讀研的時候還做了RSA矩陣擴展,將其算法基礎從素數擴展到矩陣,有興趣的可以繼續交流。

非對稱算法通過公私鈅分別加解密方式給信息交換帶來了巨大的變化,具體表現在:

1)在不安全的環境中傳遞敏感信息成爲可能。從上文可以知道,公鑰是完全公開任意傳播的,通過公鑰是無法(或極其困難)推算出私鑰的,私鑰是不公開不發送不傳播的,僅僅消息接收方知道就可以,其他任何人都不需要知道。

2)多方通信所需密鑰數量急劇減少,密鑰維護工作變得異常簡化。比如N個互不信任且互有通信需求的人,如果使用對稱加密算法,則需要N!/2個密鑰,如果使用非對稱加密僅需要N個即可(每個人只需要維護自己的公私鈅對,無論和多少人通信)。

3)基於非對稱加密發展起來的數字簽名技術(見下文詳述)從數學意義上解決了自證身份問題,使得信息接收者可以確認消息發送方身份信息且不可更改。

4)密碼學問題對數學問題的依賴空前提高。之前看似無用的甚至古老的數學難題比如數論、離散對數等在此大放異彩,頗有些笑來老師在《把時間當做朋友》裏面表達的"技不壓身"的現實映射。

2.散列(哈希)算法

我們使用各種雲盤、虛擬存儲空間應用的時候一定都有類似的體會,上傳一個明明很大的文件,可是速度卻非常快,而有時上傳一個小得多的文件卻似乎進度條要走很久。這種現象的可能的一個祕密就是接下來要講的散列算法(也叫數據摘要或者哈希算法,哈希是HASH的音譯)。

實際上,雲盤類產品對相同文件只會保留一份真實的存儲,多個使用相同文件的用戶只需“索引”到該存儲位置即可。判斷兩個文件是否相同用到的就是散列算法:

散列算法將任意長度的二進制值映射爲較短的固定長度的二進制值,這個小的二進制值稱爲哈希值。哈希值是一段數據唯一且極其緊湊的數值表示形式。如果散列一段明文而且哪怕只更改該段落的一個字母,隨後的散列值都將產生不同的值。要找到散列爲同一個值的兩個不同的輸入,在計算上是不可能的,所以數據的散列值可以檢驗數據的完整性。一般用於快速查找和加密算法。

本質上,散列算法的目的不是爲了“加密”而是爲了抽取“數據特徵”,你也可以把給定數據的散列值理解爲該數據的“指紋信息”,一個可靠的散列算法F需要滿足:

1. 對於給定的數據M,很容易算出哈希值X=F(M);

2. 根據X無法算出M;

3. 很難找到M和N令F(M)=F(N)。

我來解釋一下:

對於第一點,通常哈希值的長度是固定的(爲什麼固定,一個很重要的原因是便於構造通信包結構,散列的應用場景通常是不可靠的網絡傳輸而非本地存儲),比如比特幣使用的SHA256摘要算法對任意長度的輸入給出的是256bit的輸出。

對於第二點,散列算法是不可逆的,甚至是以丟失部分原始信息作爲代價,因此我個人認爲散列加密算法的提法是有問題的,加密意味着可以解密,單純的擾亂稱爲加密並不合適。也許所謂的散列加密是和散列校驗對應的,也就說兩種應用的場景不同,散列加密的核心是擾亂,散列校驗的核心是校驗。

對於第三點,這是散列函數真正的挑戰。假設找到了一對(M,N)使得等式成立就成爲該算法找到了一次碰撞,對散列算法健壯性的分析就是分析其抗強碰撞能力。可以理解的是,碰撞的出現將使得散列算法本身存在的意義消失了,因爲發現了不同的人擁有相同的指紋。

比特幣使用的散列算法是SHA256,他是安全散列算法SHA(Secure Hash Algorithm)系列算法的一種(另外還有SHA-1、SHA-224、SHA-384 和 SHA-512 等變體),SHA是美國國家安全局 (NSA) 設計,美國國家標準與技術研究院(NIST) 發佈的,主要適用於數字簽名標準(DigitalSignature Standard DSS)裏面定義的數字簽名算法(Digital Signature Algorithm DSA)。可以到這裏詳細瞭解。

最後,我要解釋一下二次散列問題,看過比特幣協議的讀者可能注意到工作量證明和密鑰編碼過程中多次使用了二次哈希,如SHA256(SHA256(k))或者RIPEMD160(SHA256(K)),這種方式帶來的好處是增加了工作量或者在不清楚協議的情況下增加破解難度,從安全性角度並沒有顯著增加(如果是暴力窮舉破解的話,需要增加一倍破解時間)。真正的二次哈希是基於加鹽的哈希,什麼意思呢?對於特定的待散列數據和特定的散列算法,可以知道散列值是一定的,這種情況下如果用散列保護敏感數據(理論上是不合適的,但是國內外存在大量的使用散列來保護用戶密碼的情況),那就很容易使用字典攻擊反向推算,比如我計算123456的SHA256值就可以反推了,解決辦法就是先做一次散列,再加一次隨機數據以後再做一次散列,隨機數據就是所謂的鹽。

3.數字簽名

有了非對稱加密和散列算法的準備,我們現在可以進一步認識數字簽名了。顧名思義,數字簽名就是在數字世界裏用於身份辨識的一種解決方案。不需要騎縫章,騎縫簽名,也不需要筆跡專家,數字簽名即具有不可抵賴性。

簡單地說,所謂數字簽名就是附加在數據單元上的一些數據,或是對數據單元所作的密碼變換。這種數據或變換允許數據單元的接收者用以確認數據單元的來源和數據單元的完整性並保護數據,防止被人(例如接收者)進行僞造。它是對電子形式的消息進行簽名的一種方法,一個簽名消息能在一個通信網絡中傳輸。基於公鑰密碼體制和私鑰密碼體制都可以獲得數字簽名,主要是基於公鑰密碼體制的數字簽名。

上述解釋稍顯學術,我們換種說法表述:所謂數字簽名就是簽名人用自己的私鑰對待簽名數據的摘要進行加密得到的值就是簽名值。簽名者發送數據簽名時需要把待簽名數據和簽名值一起發送給對方。

注意,簽名對象並非待簽名數據而是待簽名數據的摘要,爲什麼呢?因爲非對稱加密的速度通常都比較慢,直接對原始數據私鑰加密是很慢的而且也沒有必要。

如何驗證簽名呢?接收方首先使用簽名者的公鑰對簽名值解密即可得到摘要值,然後使用約定的算法對待簽名數據進行散列運算後和解密得到的摘要值進行比較即可驗證。

這裏有一個圖形化的數字簽名過程有助於理解數字簽名的整個過程。

從以上數字簽名的整個過程描述來看,數字簽名的核心在於簽名,在於證明這份數據是簽名者發出的、不可抵賴的。待簽名數據本身的保密不是數字簽名方案要考慮的問題。

4.可讀性編碼

嚴格來講,編碼部分不是密碼學理論的核心內容,不過爲了便於下文能說清楚,我就把可讀性編碼放到這裏簡單說說。

可讀性編碼很好理解,就是不改變信息內容僅改變內容的表現形式,部分編碼方式還加入了容錯校驗功能,通常是爲了保證更好的通信傳輸。

比如二進制的1111對應十進制的15這就是一次編碼。是用十進制對二進制進行編碼,現在有個問題,我拿到一個編碼後的數據,如何知道該數據是使用了哪種形式的編碼呢?這個是通過前綴來實現的,例如,比特幣地址的前綴是0(十六進制是0x00),而對私鑰編碼時前綴是128(十六進制是0x80)。

二、比特幣實踐

從現在開始,我們開始真刀實槍了,先看看比特幣的編碼世界。

1.Base58和Base58Check編碼

這裏請允許我拿來主義,我覺得王秒等多位老師翻譯的Andreas M. Antonopoulos所著《精通比特幣》對這個問題已經解釋的很清楚了,更詳細的描述還可以看看這裏

爲了更簡潔方便地表示長串的數字,許多計算機系統會使用一種以數字和字母組成的大於十進制的表示法。例如,傳統的十進制計數系統使用0-9十個數字,而十六進制系統使用了額外的 A-F 六個字母。一個同樣的數字,它的十六進制表示就會比十進制表示更短。更進一步,Base64使用了26個小寫字母、26個大寫字母、10個數字以及兩個符號(例如“+”和“/”),用於在電子郵件這樣的基於文本的媒介中傳輸二進制數據。Base64通常用於編碼郵件中的附件。Base58是一種基於文本的二進制編碼格式,用在比特幣和其它的加密貨幣中。這種編碼格式不僅實現了數據壓縮,保持了易讀性,還具有錯誤診斷功能。Base58是Base64編碼格式的子集,同樣使用大小寫字母和10個數字,但捨棄了一些容易錯讀和在特定字體中容易混淆的字符。具體地,Base58不含Base64中的0(數字0)、O(大寫字母o)、l(小寫字母L)、I(大寫字母i),以及“+”和“/”兩個字符。簡而言之,Base58就是由不包括(0,O,l,I)的大小寫字母和數字組成。

需要注意的是,Base58編碼是不含校驗信息的,Base58Check是一種常用在比特幣中的Base58編碼格式,增加了錯誤校驗碼來檢查數據在轉錄中出現的錯誤。校驗碼長4個字節,添加到需要編碼的數據之後。

爲了使用Base58Check編碼格式對數據(數字)進行編碼,首先我們要對數據添加一個稱作“版本字節”的前綴,這個前綴用來明確需要編碼的數據的類型。例如,比特幣地址的前綴是0(十六進制是0x00),而對私鑰編碼時前綴是128(十六進制是0x80)。 表4-1會列出一些常見版本的前綴。

接下來,我們計算“雙哈希”校驗碼,意味着要對之前的結果(前綴和數據)運行兩次SHA256哈希算法:

checksum = SHA256(SHA256(prefix+data))

在產生的長32個字節的哈希值(兩次哈希運算)中,我們只取前4個字節。這4個字節就作爲校驗碼。校驗碼會添加到數據之後。結果由三部分組成:前綴、數據和校驗碼。

2.密鑰、地址與錢包

先說結論:

1.密鑰通常指的是保護比特幣資產的對應於所有權用戶的私鑰,個別時候也會模糊的統稱私鑰和公鑰爲密鑰,這裏我們以狹義的私鑰解釋爲準。

2.地址大部分情況下是指對公鑰的封裝(個別時候除了公鑰還有腳本)。

3.錢包是私鑰的容器,通常通過有序文件或者簡單的數據庫實現。比特幣錢包包含私鑰和公鑰數據,儘管公鑰數據理論是是不需要存儲的。

2.1私鑰保護

私鑰必須保密。私鑰的機密性需求事實情況是,在實踐中相當難以實現,因爲該需求與同樣重要的安全對象可用性相互矛盾。當你需要爲了避免私鑰丟失而存儲備份時,會發現維護私鑰私密性是一件相當困難的事情。通過密碼加密內有私鑰的錢包可能要安全一點,但那個錢包也需要備份。有時,例如用戶因爲要升級或重裝錢包軟件,而需要把密鑰從一個錢包轉移到另一個。私鑰備份也可能需要存儲在紙張上(參見“4.5.4 紙錢包”一節)或者外部存儲介質裏,比如U盤。但如果一旦備份文件失竊或丟失呢?這些矛盾的安全目標推進了便攜、方便、可以被衆多不同錢包和比特幣客戶端理解的加密私鑰標準BIP0038的出臺。

BIP0038提出了一個通用標準,使用一個口令加密私鑰並使用Base58Check對加密的私鑰進行編碼,這樣加密的私鑰就可以安全地保存在備份介質裏,安全地在錢包間傳輸,保持密鑰在任何可能被暴露情況下的安全性。這個加密標準使用了AES,這個標準由NIST建立,並廣泛應用於商業和軍事應用的數據加密。


2.2公鑰與地址

我們知道比特幣協議的區塊鏈實際上是對交易的維護而不是對賬戶的維護,交易數據本身並不需要私鑰,因此對公鑰的封裝也就是地址就顯得格外重要,需要兼顧安全,效率和擴展。

從公鑰到地址經歷瞭如下過程:

A = RIPEMD160(SHA256(K))

公式中,K是公鑰,A是生成的比特幣地址。比特幣地址與公鑰不同。比特幣地址是由公鑰經過單向的哈希函數生成的

以公鑰 K 爲輸入,計算其SHA256哈希值,並以此結果計算RIPEMD160 哈希值,得到一個長度爲160比特(20字節)的數字後進行Base58Check編碼即可得到比特幣地址。從編碼數據結構的視角看,是下圖:

需要注意的是,從地址已經無法反推公鑰信息,因此,需要將私鑰以及對應的公鑰、地址一起存儲。

2.3比特幣錢包

比特幣錢包要解決的核心問題是私鑰管理,早期的方式是隨機生成私鑰池並一次一密,這當然是安全性很高的方案。但是對存儲,導入導出備份帶來了極大的挑戰,畢竟私鑰丟了誰也沒有辦法。改進的私鑰管理辦法將私鑰鏈式管理起來了,見下圖:

生成鏈式結構的過程如下:


3.區塊鏈

區塊鏈可以理解爲數據結構概念中的鏈表(和線性表略有不同的是可能有分叉),這裏我們只需要大致瞭解區塊數據結構以及每一塊大致的意思,這些結構信息將會在交易和挖礦部分進行詳細講解。

區塊鏈可以理解爲運行在去中心化網絡中的,所有節點(挖礦節點)共同維護的交易數據庫,這個數據庫是以鏈式的形式組織交易數據的,每一個鏈表的塊被稱爲區塊或者block。

3.1 區塊結構

區塊是一種被包含在公開賬簿(區塊鏈)裏的聚合了交易信息的容器數據結構。它由一個包含元數據的區塊頭和緊跟其後的構成區塊主體的一長串交易組成。

上表中的1-9應該是1-9個字節,否則會引起歧義。


3.2 區塊頭

區塊頭由三組區塊元數據組成。首先是一組引用父區塊哈希值的數據,這組元數據用於將該區塊與區塊鏈中前一區塊相連接。第二組元數據,即難度、時間戳和nonce,與挖礦競爭相關。第三組元數據是merkle樹根(一種用來有效地總結區塊中所有交易的數據結構)。

Nonce、難度目標和時間戳會用於挖礦過程,Merkle根用來索引和組織該區塊所有的交易信息,其結構見下一節。

因此區塊頭之間的連接大約像下圖所示

從上圖我們可以知道如何避免雙重支付問題,因爲收款人有辦法對這筆支付之前的所有消息進行檢索直至追溯到原始的挖礦區塊,實際上比特幣世界裏的每一枚比特幣都是被標記可溯源,雙重支付是可以避免的。

3.3 Merkle Tree

Merkle Tree,是一種樹(數據結構中所說的樹),網上大都稱爲Merkle Hash Tree,這是因爲 它所構造的Merkle Tree的所有節點都是Hash值。Merkle Tree具有以下特點:

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

2. Merkle樹的葉子節點上的value,是由你指定的,這主要看你的設計了,如Merkle Hash Tree會將數據的Hash值作爲葉子節點的值;

3 非葉子節點的value是根據它下面所有的葉子節點值,然後按照一定的算法計算而得出的。如Merkle Hash Tree的非葉子節點value的計算方法是將該節點的所有子節點進行組合,然後對組合結果進行hash計算所得出的hash value。

例如,下圖就是一個Merkle Hash Tree形狀,如果它是Merkle Hash Tree,則節點7的hash value必須是通過節點15、16上的value計算而得到.

在處理比對或驗證的應用場景中時,特別是在分佈式環境下進行比對或驗證時,Merkle Tree會大大減少數據的傳輸量以及計算的複雜度。例如,就拿圖一舉例,假如是 15,16.......30是一個個數據塊的hash值,我把這些數據從A傳輸到B,數據傳輸到B後,我想驗證下傳輸到B上的數據的有效性型(驗證數據是否在傳輸過程中發生變化),只需要驗證A 和 B上所構造的Merkle

Tree的root節點值是否一致即可,如果一致,表示數據是有效的,傳輸過程中沒有發生改變。假如在傳輸過程中,15對應的數據被人篡改,通過Merkle Tree很容易定位找到(因爲此時,節點0,1,3,7,15對應的hash值都發生了變化)

需要解釋的是交易數據是怎麼構建成數的呢,其實很簡單:首先將所有交易作爲葉子節點,兩兩相鄰分組(總的交易數量如果是奇數就把單個的那個複製一份),然後對每一對交易分別計算哈希並依此向上構建樹直至根節點,如下圖所示:


4.交易


再次強調的是,比特幣網絡中流轉的是交易信息,每個賬戶的餘額是通過交易信息推算出來的,交易信息是雙向的,有一個輸入必定對應一個輸出。

3.1交易輸入輸出


每一筆交易,out的總額應該等於in的總額。但是,在這個交易單裏,只會有out的Value,沒有in的Value,而是通過in的Pervious與index,追溯到上一個交易單的某一個out,獲得Value。

一次send bitcoin,剩下的錢,應該out給自己,否則這個錢就丟了。

情況列舉:

我有10個BTC,是某一次交易獲得的,我要送給朋友A,10個BTC。這時候,有一個in,一個out。

我有10個BTC,是某一次交易獲得的,我要送給朋友A,5個BTC,這時候,有一個in,兩個out,一個指向朋友5個BTC,一個指向我自己,得到剩下的5個BTC。

我有10個BTC,是以前的兩次交易獲得的,我要送給朋友A,10個BTC,這時候,有兩個in,一個out。

我有10個BTC,是以前的兩次交易獲得的,其中一次獲得了6個BTC,另一次獲得了4個BTC,我要送給我的朋友7個BTC,這時候,有兩個in,兩個out。

比特幣交易的基本單位是未經使用的一個交易輸出,簡稱UTXO。UTXO是不能再分割、被所有者鎖住或記錄於區塊鏈中的並被整個網絡識別成貨幣單位的一定量的比特幣貨幣。這句話什麼意思呢?比特幣交易除了挖礦獲取以外,都是零和的,因爲區塊鏈不維護餘額信息也沒有餘額概念,區塊鏈只有交易信息。舉個例子,你有10個比特幣現在需要支付2個出去,那麼交易數據維護的是一個輸入(未經使用的10個比特幣)和2個輸出(一個是2個幣對應的地址),還有一個是8個幣對應地址是你自己的地址。


3.2交易過程

交易的基本訴求,是付款人(payer)匯款給收款人(payee)。技術挑戰是加密(cryptography),目的是不讓第三者截獲甚至篡改匯款金額。

下圖解釋了 Owner0 給 Owner1以及後續 匯款的交易機制,截圖如下。

1. Owner0 先查到 Owner1 的公鑰。用 Owner1 的公鑰(Public Key)把匯款詳情加密。這樣,只有 Owner1 本人用自己的私鑰(Private Key),才能打開加了密的匯款詳情。在圖例中,沒有畫匯款詳情。不過這個小小的敘述的疏忽無妨大雅。

2. 爲了方便 Owner1 驗證這筆匯款的確來自 Owner0,而不是別人,Owner0 發出的匯款單裏,除了有加了密的匯款詳情,還有 Owner0 的數字簽名(Signature)。Owner1 拿到匯款時,爲了驗證這筆匯款的確來自 Owner0,他可以用 Owner0 的公鑰,來驗證匯款單中 Owner0 的數字簽名。

3. Owner0 發出匯款單時,匯款單不僅僅投遞到 Owner1,而且還要廣而告之,任何人只要願意參與 BitCoin 審計,都可以收到全球所有人發出的所有匯款單。

4. 沿用 1、2、3 的原理,Owner1 給 Owner2 匯款,然後 Owner2 給 Owner3 匯款。BitCoin 通過 Hash 機制,把涉及同一枚 BitCoin 的所有匯款交易(Tranaction)串連起來,目的是爲了追查重複付款(double spending)的欺詐行爲。

單獨來看交易創建過程:

收款方對交易進行驗證:



4.挖礦原理

挖礦的本質意義是挖礦節點爭奪記賬權!主觀上來說,挖礦節點獲得了挖礦獎勵及交易費,客觀上來說,這保證了區塊鏈按照特定規則持續穩定的被維護。

挖礦的具體實現就是在難度一定的情況下通過暴力雙SHA256哈希運算獲取滿足難度taget的Nonce值,所謂的工作量證明就是無數次哈希運算窮舉並比對的過程。

“挖礦”算法我們可以參考區塊頭結構解說如下:


第一步:找到區塊版本號version。

第二步:找到上一個區塊的hash值(父區塊哈希值):prev_hash。

第三步:輸入記錄交易的hash樹的根節點hash值(Merkle根):root_hash。

第四步:更新的時間(時間戳):time。

第五步:全網當前難度(難度目標):difficulty

針對難度目標需要說明:

難度在區塊中以“尾數-指數”的格式,編碼並存儲,這種格式稱作“難度位”。這種編碼的首字節表示指數,後面的3字節表示尾數(係數)。以區塊277316爲例,難度位的值爲0x1903a30c,0x19是指數(exponent)的十六進制格式,後半部0x03a30c是係數(coefficient)。

第六步:自己找一個隨機數Nonce:這個就是反覆試的部分,不斷遞增該數字並做哈希運算直到對應哈希值小於難度指定的taget值。

把以上6個參數作爲輸入,做二次SHA256運算,形似於

SHA256(SHA256(version , prev_hash , root_hash , time , difficulty, random))

最終得到結果result。最後把結果result提交給系統,由系統判斷這個計算結果是否有效(result<target爲有效)。若判定結果爲有效,你就產生了一個新的區塊,並會告知全網。

target通過difficulty可以計算得到:

target = coefficient * 2^(8 * (exponent – 3))

算法規定:一個新的區塊的第一筆交易必須將特定數目的比特幣發到某個地址,當然這個地址肯定會設成挖礦人自己的比特幣地址,從而獲得系統的比特幣獎勵。


5.總結

比特幣理論以密碼學爲支撐,構建了一個完備、安全、去中心化的數字貨幣體系,解決了數字資產所有權問題、雙重支付問題、現實世界的通貨膨脹問題甚至還預留了機制使得構建在資產轉移之上的智能合同成爲可能。比特幣當然是偉大的創造,期待比特幣有更好的未來。

另外,本書成文過程中參考了王秒等老師翻譯的《精通比特幣》,李鈞等老師的《比特幣》以及巴比特社區的大量知識,感謝他們。



作者:怒馬2048
鏈接:https://www.jianshu.com/p/225ff9439132
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章