〇、序言
貨幣由于其天然屬性決定了其與安全不可分割的聯(lián)系,從最早的金庫(kù)、保險(xiǎn)柜、鏢局到后來(lái)的ATM機(jī)、運(yùn)鈔車(chē);從存折到銀行卡,從口令卡到優(yōu)盾,安全技術(shù)的進(jìn)步一步步推動(dòng)著金融防護(hù)領(lǐng)域的更新。
傳統(tǒng)的貨幣的安全需求,密碼學(xué)是安全手段,是從“可用”到“安心用”的升級(jí)。而對(duì)比特幣來(lái)說(shuō),密碼學(xué)本身就是比特幣體系的一部分,沒(méi)有密碼學(xué)支撐的比特幣體系會(huì)完全崩塌,徹底“不可用”。本質(zhì)上來(lái)說(shuō),比特幣和密碼學(xué)是融為一體的,比特幣是自帶安全屬性的數(shù)字貨幣。因此,對(duì)比特幣用戶來(lái)說(shuō),了解比特幣背后的密碼學(xué)理論,有助于更好的理解比特幣;同時(shí),通過(guò)密碼學(xué)理論的分享,也可以順便感受一下人類(lèi)智慧的偉大。畢竟,在我眼里,密碼學(xué)理論是大量聰慧的頭腦審慎思考的結(jié)果,精致而又巧妙之處比比皆是。
一、密碼學(xué)理論
比特幣本身并沒(méi)有創(chuàng)造新的密碼學(xué)成果,但比特幣利用現(xiàn)有密碼學(xué)成果構(gòu)建了一個(gè)令人驚奇的全新的數(shù)字貨幣世界:去中心化、區(qū)塊鏈、可編程貨幣等成果即使拋開(kāi)比特幣本身而言也是值得贊賞的洞見(jiàn)。
首先,現(xiàn)代密碼學(xué)理論的共識(shí)遵循“柯克霍夫原則”:
柯克霍夫原則由奧古斯特·柯克霍夫在19世紀(jì)提出:密碼系統(tǒng)應(yīng)該就算被所有人知道系統(tǒng)的運(yùn)作步驟,仍然是安全的。
這個(gè)是什么意思呢,拿鑰匙和鎖的例子來(lái)說(shuō),研制和生產(chǎn)鎖具(包括鑰匙)的工藝是完全公開(kāi)的,鎖具被攻破只有兩種可能:一是證明工藝有漏洞,不需要拿到原裝鑰匙也能打開(kāi)。二是窮盡各種鑰匙可能,在可接受的時(shí)間里能夠從概率意義上試出來(lái)(暴力破解)。
算法是公開(kāi)的,唯一需要保護(hù)的是密鑰,這是我們下文討論的基礎(chǔ)。
1.非對(duì)稱加密
先看對(duì)稱加密很好理解也符合直覺(jué):
對(duì)稱加密:對(duì)同一份敏感數(shù)據(jù),加密解密密鑰是相同的。
非對(duì)稱加密呢:
非對(duì)稱加密算法需要兩個(gè)密鑰:公開(kāi)密鑰(publickey)和私有密鑰(privatekey)。公開(kāi)密鑰與私有密鑰是一對(duì),如果用公開(kāi)密鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的私有密鑰才能解密;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密,那么只有用對(duì)應(yīng)的公開(kāi)密鑰才能解密。因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰,所以這種算法叫作非對(duì)稱加密算法。 非對(duì)稱加密算法實(shí)現(xiàn)機(jī)密信息交換的基本過(guò)程是:甲方生成一對(duì)密鑰并將其中的一把作為公用密鑰向其它方公開(kāi);得到該公用密鑰的乙方使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專(zhuān)用密鑰對(duì)加密后的信息進(jìn)行解密。
我們用一幅圖來(lái)說(shuō)明:

在上文的非對(duì)稱加密部分,密鑰A就是公開(kāi)密鑰(簡(jiǎn)稱公鑰),密鑰B就是私有密鑰(簡(jiǎn)稱私鑰)。道理都懂,問(wèn)題有意思在什么地方呢?非對(duì)稱加密方式下密鑰A和密鑰B是怎么找到的以及怎么實(shí)現(xiàn)的?我們舉例說(shuō)明:
假設(shè)我們現(xiàn)在已經(jīng)找到了(具體怎么找的后面會(huì)講)公鑰(3233,17)和私鑰(3233, 2753)。
注意,公鑰和私鑰不一定只有一個(gè)數(shù)字,是可以有多個(gè)的,具體幾個(gè)數(shù)字依賴于非對(duì)稱加密算法。
假設(shè)現(xiàn)在明文待加密信息是數(shù)字65,我們首先給出加密公式:

解釋一下,c代表加密后數(shù)字,(n,e)對(duì)應(yīng)我們的公鑰對(duì),m代表明文,≡的意思是同模運(yùn)算,比如60≡4(mod 7),60對(duì)4取模后等于4。好了我們開(kāi)始計(jì)算密文:

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

d對(duì)應(yīng)私鑰的2753,其余字母和加密過(guò)程相同,于是解密運(yùn)算為:

我們得到了原來(lái)的明文數(shù)據(jù)65,這個(gè)例子可以看到加密和解密數(shù)據(jù)是不同的。
以上我們舉例使用的算法是大名鼎鼎的地球主流非對(duì)稱加密算法RSA,有關(guān)RSA的介紹參考阮一峰老師的文章。實(shí)際上我上面用到的數(shù)字也出自該文,實(shí)在是時(shí)間有限無(wú)法深入講解RSA的細(xì)節(jié)大家可以自行學(xué)習(xí)。比特幣體系實(shí)際使用的非對(duì)稱算法是橢圓曲線加密(ECC),可以到這里詳細(xì)了解。
從上面的例子我們知道滿足非對(duì)稱加密的密鑰對(duì)是存在的,同時(shí)我們也做了加解密?chē)L試。實(shí)際上,非對(duì)稱加密算法的核心依賴于特定的數(shù)學(xué)難題,比如上文的RSA依賴于大數(shù)分解難題,如果該難題被破解了,算法本身也就被攻破了。另外,我讀研的時(shí)候還做了RSA矩陣擴(kuò)展,將其算法基礎(chǔ)從素?cái)?shù)擴(kuò)展到矩陣,有興趣的可以繼續(xù)交流。
非對(duì)稱算法通過(guò)公私鈅分別加解密方式給信息交換帶來(lái)了巨大的變化,具體表現(xiàn)在:
1)在不安全的環(huán)境中傳遞敏感信息成為可能。從上文可以知道,公鑰是完全公開(kāi)任意傳播的,通過(guò)公鑰是無(wú)法(或極其困難)推算出私鑰的,私鑰是不公開(kāi)不發(fā)送不傳播的,僅僅消息接收方知道就可以,其他任何人都不需要知道。
2)多方通信所需密鑰數(shù)量急劇減少,密鑰維護(hù)工作變得異常簡(jiǎn)化。比如N個(gè)互不信任且互有通信需求的人,如果使用對(duì)稱加密算法,則需要N!/2個(gè)密鑰,如果使用非對(duì)稱加密僅需要N個(gè)即可(每個(gè)人只需要維護(hù)自己的公私鈅對(duì),無(wú)論和多少人通信)。
3)基于非對(duì)稱加密發(fā)展起來(lái)的數(shù)字簽名技術(shù)(見(jiàn)下文詳述)從數(shù)學(xué)意義上解決了自證身份問(wèn)題,使得信息接收者可以確認(rèn)消息發(fā)送方身份信息且不可更改。
4)密碼學(xué)問(wèn)題對(duì)數(shù)學(xué)問(wèn)題的依賴空前提高。之前看似無(wú)用的甚至古老的數(shù)學(xué)難題比如數(shù)論、離散對(duì)數(shù)等在此大放異彩,頗有些笑來(lái)老師在《把時(shí)間當(dāng)做朋友》里面表達(dá)的"技不壓身"的現(xiàn)實(shí)映射。
2.散列(哈希)算法
我們使用各種云盤(pán)、虛擬存儲(chǔ)空間應(yīng)用的時(shí)候一定都有類(lèi)似的體會(huì),上傳一個(gè)明明很大的文件,可是速度卻非???,而有時(shí)上傳一個(gè)小得多的文件卻似乎進(jìn)度條要走很久。這種現(xiàn)象的可能的一個(gè)秘密就是接下來(lái)要講的散列算法(也叫數(shù)據(jù)摘要或者哈希算法,哈希是HASH的音譯)。
實(shí)際上,云盤(pán)類(lèi)產(chǎn)品對(duì)相同文件只會(huì)保留一份真實(shí)的存儲(chǔ),多個(gè)使用相同文件的用戶只需“索引”到該存儲(chǔ)位置即可。判斷兩個(gè)文件是否相同用到的就是散列算法:
散列算法將任意長(zhǎng)度的二進(jìn)制值映射為較短的固定長(zhǎng)度的二進(jìn)制值,這個(gè)小的二進(jìn)制值稱為哈希值。哈希值是一段數(shù)據(jù)唯一且極其緊湊的數(shù)值表示形式。如果散列一段明文而且哪怕只更改該段落的一個(gè)字母,隨后的散列值都將產(chǎn)生不同的值。要找到散列為同一個(gè)值的兩個(gè)不同的輸入,在計(jì)算上是不可能的,所以數(shù)據(jù)的散列值可以檢驗(yàn)數(shù)據(jù)的完整性。一般用于快速查找和加密算法。
本質(zhì)上,散列算法的目的不是為了“加密”而是為了抽取“數(shù)據(jù)特征”,你也可以把給定數(shù)據(jù)的散列值理解為該數(shù)據(jù)的“指紋信息”,一個(gè)可靠的散列算法F需要滿足:
1. 對(duì)于給定的數(shù)據(jù)M,很容易算出哈希值X=F(M);
2. 根據(jù)X無(wú)法算出M;
3. 很難找到M和N令F(M)=F(N)。
我來(lái)解釋一下:
對(duì)于第一點(diǎn),通常哈希值的長(zhǎng)度是固定的(為什么固定,一個(gè)很重要的原因是便于構(gòu)造通信包結(jié)構(gòu),散列的應(yīng)用場(chǎng)景通常是不可靠的網(wǎng)絡(luò)傳輸而非本地存儲(chǔ)),比如比特幣使用的SHA256摘要算法對(duì)任意長(zhǎng)度的輸入給出的是256bit的輸出。
對(duì)于第二點(diǎn),散列算法是不可逆的,甚至是以丟失部分原始信息作為代價(jià),因此我個(gè)人認(rèn)為散列加密算法的提法是有問(wèn)題的,加密意味著可以解密,單純的擾亂稱為加密并不合適。也許所謂的散列加密是和散列校驗(yàn)對(duì)應(yīng)的,也就說(shuō)兩種應(yīng)用的場(chǎng)景不同,散列加密的核心是擾亂,散列校驗(yàn)的核心是校驗(yàn)。
對(duì)于第三點(diǎn),這是散列函數(shù)真正的挑戰(zhàn)。假設(shè)找到了一對(duì)(M,N)使得等式成立就成為該算法找到了一次碰撞,對(duì)散列算法健壯性的分析就是分析其抗強(qiáng)碰撞能力??梢岳斫獾氖牵鲎驳某霈F(xiàn)將使得散列算法本身存在的意義消失了,因?yàn)榘l(fā)現(xiàn)了不同的人擁有相同的指紋。
比特幣使用的散列算法是SHA256,他是安全散列算法SHA(Secure Hash Algorithm)系列算法的一種(另外還有SHA-1、SHA-224、SHA-384 和 SHA-512 等變體),SHA是美國(guó)國(guó)家安全局 (NSA) 設(shè)計(jì),美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院(NIST) 發(fā)布的,主要適用于數(shù)字簽名標(biāo)準(zhǔn)(DigitalSignature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA)??梢缘竭@里詳細(xì)了解。
最后,我要解釋一下二次散列問(wèn)題,看過(guò)比特幣協(xié)議的讀者可能注意到工作量證明和密鑰編碼過(guò)程中多次使用了二次哈希,如SHA256(SHA256(k))或者RIPEMD160(SHA256(K)),這種方式帶來(lái)的好處是增加了工作量或者在不清楚協(xié)議的情況下增加破解難度,從安全性角度并沒(méi)有顯著增加(如果是暴力窮舉破解的話,需要增加一倍破解時(shí)間)。真正的二次哈希是基于加鹽的哈希,什么意思呢?對(duì)于特定的待散列數(shù)據(jù)和特定的散列算法,可以知道散列值是一定的,這種情況下如果用散列保護(hù)敏感數(shù)據(jù)(理論上是不合適的,但是國(guó)內(nèi)外存在大量的使用散列來(lái)保護(hù)用戶密碼的情況),那就很容易使用字典攻擊反向推算,比如我計(jì)算123456的SHA256值就可以反推了,解決辦法就是先做一次散列,再加一次隨機(jī)數(shù)據(jù)以后再做一次散列,隨機(jī)數(shù)據(jù)就是所謂的鹽。
3.數(shù)字簽名
有了非對(duì)稱加密和散列算法的準(zhǔn)備,我們現(xiàn)在可以進(jìn)一步認(rèn)識(shí)數(shù)字簽名了。顧名思義,數(shù)字簽名就是在數(shù)字世界里用于身份辨識(shí)的一種解決方案。不需要騎縫章,騎縫簽名,也不需要筆跡專(zhuān)家,數(shù)字簽名即具有不可抵賴性。
簡(jiǎn)單地說(shuō),所謂數(shù)字簽名就是附加在數(shù)據(jù)單元上的一些數(shù)據(jù),或是對(duì)數(shù)據(jù)單元所作的密碼變換。這種數(shù)據(jù)或變換允許數(shù)據(jù)單元的接收者用以確認(rèn)數(shù)據(jù)單元的來(lái)源和數(shù)據(jù)單元的完整性并保護(hù)數(shù)據(jù),防止被人(例如接收者)進(jìn)行偽造。它是對(duì)電子形式的消息進(jìn)行簽名的一種方法,一個(gè)簽名消息能在一個(gè)通信網(wǎng)絡(luò)中傳輸?;诠€密碼體制和私鑰密碼體制都可以獲得數(shù)字簽名,主要是基于公鑰密碼體制的數(shù)字簽名。
上述解釋稍顯學(xué)術(shù),我們換種說(shuō)法表述:所謂數(shù)字簽名就是簽名人用自己的私鑰對(duì)待簽名數(shù)據(jù)的摘要進(jìn)行加密得到的值就是簽名值。簽名者發(fā)送數(shù)據(jù)簽名時(shí)需要把待簽名數(shù)據(jù)和簽名值一起發(fā)送給對(duì)方。
注意,簽名對(duì)象并非待簽名數(shù)據(jù)而是待簽名數(shù)據(jù)的摘要,為什么呢?因?yàn)榉菍?duì)稱加密的速度通常都比較慢,直接對(duì)原始數(shù)據(jù)私鑰加密是很慢的而且也沒(méi)有必要。
如何驗(yàn)證簽名呢?接收方首先使用簽名者的公鑰對(duì)簽名值解密即可得到摘要值,然后使用約定的算法對(duì)待簽名數(shù)據(jù)進(jìn)行散列運(yùn)算后和解密得到的摘要值進(jìn)行比較即可驗(yàn)證。
這里有一個(gè)圖形化的數(shù)字簽名過(guò)程有助于理解數(shù)字簽名的整個(gè)過(guò)程。
從以上數(shù)字簽名的整個(gè)過(guò)程描述來(lái)看,數(shù)字簽名的核心在于簽名,在于證明這份數(shù)據(jù)是簽名者發(fā)出的、不可抵賴的。待簽名數(shù)據(jù)本身的保密不是數(shù)字簽名方案要考慮的問(wèn)題。
4.可讀性編碼
嚴(yán)格來(lái)講,編碼部分不是密碼學(xué)理論的核心內(nèi)容,不過(guò)為了便于下文能說(shuō)清楚,我就把可讀性編碼放到這里簡(jiǎn)單說(shuō)說(shuō)。
可讀性編碼很好理解,就是不改變信息內(nèi)容僅改變內(nèi)容的表現(xiàn)形式,部分編碼方式還加入了容錯(cuò)校驗(yàn)功能,通常是為了保證更好的通信傳輸。
比如二進(jìn)制的1111對(duì)應(yīng)十進(jìn)制的15這就是一次編碼。是用十進(jìn)制對(duì)二進(jìn)制進(jìn)行編碼,現(xiàn)在有個(gè)問(wèn)題,我拿到一個(gè)編碼后的數(shù)據(jù),如何知道該數(shù)據(jù)是使用了哪種形式的編碼呢?這個(gè)是通過(guò)前綴來(lái)實(shí)現(xiàn)的,例如,比特幣地址的前綴是0(十六進(jìn)制是0x00),而對(duì)私鑰編碼時(shí)前綴是128(十六進(jìn)制是0x80)。
二、比特幣實(shí)踐
從現(xiàn)在開(kāi)始,我們開(kāi)始真刀實(shí)槍了,先看看比特幣的編碼世界。
1.Base58和Base58Check編碼
這里請(qǐng)?jiān)试S我拿來(lái)主義,我覺(jué)得王秒等多位老師翻譯的Andreas M. Antonopoulos所著《精通比特幣》對(duì)這個(gè)問(wèn)題已經(jīng)解釋的很清楚了,更詳細(xì)的描述還可以看看這里。
為了更簡(jiǎn)潔方便地表示長(zhǎng)串的數(shù)字,許多計(jì)算機(jī)系統(tǒng)會(huì)使用一種以數(shù)字和字母組成的大于十進(jìn)制的表示法。例如,傳統(tǒng)的十進(jìn)制計(jì)數(shù)系統(tǒng)使用0-9十個(gè)數(shù)字,而十六進(jìn)制系統(tǒng)使用了額外的 A-F 六個(gè)字母。一個(gè)同樣的數(shù)字,它的十六進(jìn)制表示就會(huì)比十進(jìn)制表示更短。更進(jìn)一步,Base64使用了26個(gè)小寫(xiě)字母、26個(gè)大寫(xiě)字母、10個(gè)數(shù)字以及兩個(gè)符號(hào)(例如“+”和“/”),用于在電子郵件這樣的基于文本的媒介中傳輸二進(jìn)制數(shù)據(jù)。Base64通常用于編碼郵件中的附件。Base58是一種基于文本的二進(jìn)制編碼格式,用在比特幣和其它的加密貨幣中。這種編碼格式不僅實(shí)現(xiàn)了數(shù)據(jù)壓縮,保持了易讀性,還具有錯(cuò)誤診斷功能。Base58是Base64編碼格式的子集,同樣使用大小寫(xiě)字母和10個(gè)數(shù)字,但舍棄了一些容易錯(cuò)讀和在特定字體中容易混淆的字符。具體地,Base58不含Base64中的0(數(shù)字0)、O(大寫(xiě)字母o)、l(小寫(xiě)字母L)、I(大寫(xiě)字母i),以及“+”和“/”兩個(gè)字符。簡(jiǎn)而言之,Base58就是由不包括(0,O,l,I)的大小寫(xiě)字母和數(shù)字組成。
需要注意的是,Base58編碼是不含校驗(yàn)信息的,Base58Check是一種常用在比特幣中的Base58編碼格式,增加了錯(cuò)誤校驗(yàn)碼來(lái)檢查數(shù)據(jù)在轉(zhuǎn)錄中出現(xiàn)的錯(cuò)誤。校驗(yàn)碼長(zhǎng)4個(gè)字節(jié),添加到需要編碼的數(shù)據(jù)之后。
為了使用Base58Check編碼格式對(duì)數(shù)據(jù)(數(shù)字)進(jìn)行編碼,首先我們要對(duì)數(shù)據(jù)添加一個(gè)稱作“版本字節(jié)”的前綴,這個(gè)前綴用來(lái)明確需要編碼的數(shù)據(jù)的類(lèi)型。例如,比特幣地址的前綴是0(十六進(jìn)制是0x00),而對(duì)私鑰編碼時(shí)前綴是128(十六進(jìn)制是0x80)。 表4-1會(huì)列出一些常見(jiàn)版本的前綴。
接下來(lái),我們計(jì)算“雙哈希”校驗(yàn)碼,意味著要對(duì)之前的結(jié)果(前綴和數(shù)據(jù))運(yùn)行兩次SHA256哈希算法:
checksum = SHA256(SHA256(prefix+data))
在產(chǎn)生的長(zhǎng)32個(gè)字節(jié)的哈希值(兩次哈希運(yùn)算)中,我們只取前4個(gè)字節(jié)。這4個(gè)字節(jié)就作為校驗(yàn)碼。校驗(yàn)碼會(huì)添加到數(shù)據(jù)之后。結(jié)果由三部分組成:前綴、數(shù)據(jù)和校驗(yàn)碼。
2.密鑰、地址與錢(qián)包
先說(shuō)結(jié)論:
1.密鑰通常指的是保護(hù)比特幣資產(chǎn)的對(duì)應(yīng)于所有權(quán)用戶的私鑰,個(gè)別時(shí)候也會(huì)模糊的統(tǒng)稱私鑰和公鑰為密鑰,這里我們以狹義的私鑰解釋為準(zhǔn)。
2.地址大部分情況下是指對(duì)公鑰的封裝(個(gè)別時(shí)候除了公鑰還有腳本)。
3.錢(qián)包是私鑰的容器,通常通過(guò)有序文件或者簡(jiǎn)單的數(shù)據(jù)庫(kù)實(shí)現(xiàn)。比特幣錢(qián)包包含私鑰和公鑰數(shù)據(jù),盡管公鑰數(shù)據(jù)理論是是不需要存儲(chǔ)的。
2.1私鑰保護(hù)
私鑰必須保密。私鑰的機(jī)密性需求事實(shí)情況是,在實(shí)踐中相當(dāng)難以實(shí)現(xiàn),因?yàn)樵撔枨笈c同樣重要的安全對(duì)象可用性相互矛盾。當(dāng)你需要為了避免私鑰丟失而存儲(chǔ)備份時(shí),會(huì)發(fā)現(xiàn)維護(hù)私鑰私密性是一件相當(dāng)困難的事情。通過(guò)密碼加密內(nèi)有私鑰的錢(qián)包可能要安全一點(diǎn),但那個(gè)錢(qián)包也需要備份。有時(shí),例如用戶因?yàn)橐?jí)或重裝錢(qián)包軟件,而需要把密鑰從一個(gè)錢(qián)包轉(zhuǎn)移到另一個(gè)。私鑰備份也可能需要存儲(chǔ)在紙張上(參見(jiàn)“4.5.4 紙錢(qián)包”一節(jié))或者外部存儲(chǔ)介質(zhì)里,比如U盤(pán)。但如果一旦備份文件失竊或丟失呢?這些矛盾的安全目標(biāo)推進(jìn)了便攜、方便、可以被眾多不同錢(qián)包和比特幣客戶端理解的加密私鑰標(biāo)準(zhǔn)BIP0038的出臺(tái)。
BIP0038提出了一個(gè)通用標(biāo)準(zhǔn),使用一個(gè)口令加密私鑰并使用Base58Check對(duì)加密的私鑰進(jìn)行編碼,這樣加密的私鑰就可以安全地保存在備份介質(zhì)里,安全地在錢(qián)包間傳輸,保持密鑰在任何可能被暴露情況下的安全性。這個(gè)加密標(biāo)準(zhǔn)使用了AES,這個(gè)標(biāo)準(zhǔn)由NIST建立,并廣泛應(yīng)用于商業(yè)和軍事應(yīng)用的數(shù)據(jù)加密。
2.2公鑰與地址
我們知道比特幣協(xié)議的區(qū)塊鏈實(shí)際上是對(duì)交易的維護(hù)而不是對(duì)賬戶的維護(hù),交易數(shù)據(jù)本身并不需要私鑰,因此對(duì)公鑰的封裝也就是地址就顯得格外重要,需要兼顧安全,效率和擴(kuò)展。
從公鑰到地址經(jīng)歷了如下過(guò)程:

A = RIPEMD160(SHA256(K))
公式中,K是公鑰,A是生成的比特幣地址。比特幣地址與公鑰不同。比特幣地址是由公鑰經(jīng)過(guò)單向的哈希函數(shù)生成的
以公鑰 K 為輸入,計(jì)算其SHA256哈希值,并以此結(jié)果計(jì)算RIPEMD160 哈希值,得到一個(gè)長(zhǎng)度為160比特(20字節(jié))的數(shù)字后進(jìn)行Base58Check編碼即可得到比特幣地址。從編碼數(shù)據(jù)結(jié)構(gòu)的視角看,是下圖:

需要注意的是,從地址已經(jīng)無(wú)法反推公鑰信息,因此,需要將私鑰以及對(duì)應(yīng)的公鑰、地址一起存儲(chǔ)。
2.3比特幣錢(qián)包
比特幣錢(qián)包要解決的核心問(wèn)題是私鑰管理,早期的方式是隨機(jī)生成私鑰池并一次一密,這當(dāng)然是安全性很高的方案。但是對(duì)存儲(chǔ),導(dǎo)入導(dǎo)出備份帶來(lái)了極大的挑戰(zhàn),畢竟私鑰丟了誰(shuí)也沒(méi)有辦法。改進(jìn)的私鑰管理辦法將私鑰鏈?zhǔn)焦芾砥饋?lái)了,見(jiàn)下圖:

生成鏈?zhǔn)浇Y(jié)構(gòu)的過(guò)程如下:

3.區(qū)塊鏈
區(qū)塊鏈可以理解為數(shù)據(jù)結(jié)構(gòu)概念中的鏈表(和線性表略有不同的是可能有分叉),這里我們只需要大致了解區(qū)塊數(shù)據(jù)結(jié)構(gòu)以及每一塊大致的意思,這些結(jié)構(gòu)信息將會(huì)在交易和挖礦部分進(jìn)行詳細(xì)講解。
區(qū)塊鏈可以理解為運(yùn)行在去中心化網(wǎng)絡(luò)中的,所有節(jié)點(diǎn)(挖礦節(jié)點(diǎn))共同維護(hù)的交易數(shù)據(jù)庫(kù),這個(gè)數(shù)據(jù)庫(kù)是以鏈?zhǔn)降男问浇M織交易數(shù)據(jù)的,每一個(gè)鏈表的塊被稱為區(qū)塊或者block。
3.1 區(qū)塊結(jié)構(gòu)
區(qū)塊是一種被包含在公開(kāi)賬簿(區(qū)塊鏈)里的聚合了交易信息的容器數(shù)據(jù)結(jié)構(gòu)。它由一個(gè)包含元數(shù)據(jù)的區(qū)塊頭和緊跟其后的構(gòu)成區(qū)塊主體的一長(zhǎng)串交易組成。

上表中的1-9應(yīng)該是1-9個(gè)字節(jié),否則會(huì)引起歧義。
3.2 區(qū)塊頭
區(qū)塊頭由三組區(qū)塊元數(shù)據(jù)組成。首先是一組引用父區(qū)塊哈希值的數(shù)據(jù),這組元數(shù)據(jù)用于將該區(qū)塊與區(qū)塊鏈中前一區(qū)塊相連接。第二組元數(shù)據(jù),即難度、時(shí)間戳和nonce,與挖礦競(jìng)爭(zhēng)相關(guān)。第三組元數(shù)據(jù)是merkle樹(shù)根(一種用來(lái)有效地總結(jié)區(qū)塊中所有交易的數(shù)據(jù)結(jié)構(gòu))。

Nonce、難度目標(biāo)和時(shí)間戳?xí)糜谕诘V過(guò)程,Merkle根用來(lái)索引和組織該區(qū)塊所有的交易信息,其結(jié)構(gòu)見(jiàn)下一節(jié)。
因此區(qū)塊頭之間的連接大約像下圖所示:

從上圖我們可以知道如何避免雙重支付問(wèn)題,因?yàn)槭湛钊擞修k法對(duì)這筆支付之前的所有消息進(jìn)行檢索直至追溯到原始的挖礦區(qū)塊,實(shí)際上比特幣世界里的每一枚比特幣都是被標(biāo)記可溯源,雙重支付是可以避免的。
3.3 Merkle Tree
Merkle Tree,是一種樹(shù)(數(shù)據(jù)結(jié)構(gòu)中所說(shuō)的樹(shù)),網(wǎng)上大都稱為Merkle Hash Tree,這是因?yàn)?它所構(gòu)造的Merkle Tree的所有節(jié)點(diǎn)都是Hash值。Merkle Tree具有以下特點(diǎn):
1. 它是一種樹(shù),可以是二叉樹(shù),也可以多叉樹(shù),無(wú)論是幾叉樹(shù),它都具有樹(shù)結(jié)構(gòu)的所有特點(diǎn);
2. Merkle樹(shù)的葉子節(jié)點(diǎn)上的value,是由你指定的,這主要看你的設(shè)計(jì)了,如Merkle Hash Tree會(huì)將數(shù)據(jù)的Hash值作為葉子節(jié)點(diǎn)的值;
3 非葉子節(jié)點(diǎn)的value是根據(jù)它下面所有的葉子節(jié)點(diǎn)值,然后按照一定的算法計(jì)算而得出的。如Merkle Hash Tree的非葉子節(jié)點(diǎn)value的計(jì)算方法是將該節(jié)點(diǎn)的所有子節(jié)點(diǎn)進(jìn)行組合,然后對(duì)組合結(jié)果進(jìn)行hash計(jì)算所得出的hash value。
例如,下圖就是一個(gè)Merkle Hash Tree形狀,如果它是Merkle Hash Tree,則節(jié)點(diǎn)7的hash value必須是通過(guò)節(jié)點(diǎn)15、16上的value計(jì)算而得到.

在處理比對(duì)或驗(yàn)證的應(yīng)用場(chǎng)景中時(shí),特別是在分布式環(huán)境下進(jìn)行比對(duì)或驗(yàn)證時(shí),Merkle Tree會(huì)大大減少數(shù)據(jù)的傳輸量以及計(jì)算的復(fù)雜度。例如,就拿圖一舉例,假如是 15,16.......30是一個(gè)個(gè)數(shù)據(jù)塊的hash值,我把這些數(shù)據(jù)從A傳輸?shù)紹,數(shù)據(jù)傳輸?shù)紹后,我想驗(yàn)證下傳輸?shù)紹上的數(shù)據(jù)的有效性型(驗(yàn)證數(shù)據(jù)是否在傳輸過(guò)程中發(fā)生變化),只需要驗(yàn)證A 和 B上所構(gòu)造的Merkle
Tree的root節(jié)點(diǎn)值是否一致即可,如果一致,表示數(shù)據(jù)是有效的,傳輸過(guò)程中沒(méi)有發(fā)生改變。假如在傳輸過(guò)程中,15對(duì)應(yīng)的數(shù)據(jù)被人篡改,通過(guò)Merkle Tree很容易定位找到(因?yàn)榇藭r(shí),節(jié)點(diǎn)0,1,3,7,15對(duì)應(yīng)的hash值都發(fā)生了變化)
需要解釋的是交易數(shù)據(jù)是怎么構(gòu)建成數(shù)的呢,其實(shí)很簡(jiǎn)單:首先將所有交易作為葉子節(jié)點(diǎn),兩兩相鄰分組(總的交易數(shù)量如果是奇數(shù)就把單個(gè)的那個(gè)復(fù)制一份),然后對(duì)每一對(duì)交易分別計(jì)算哈希并依此向上構(gòu)建樹(shù)直至根節(jié)點(diǎn),如下圖所示:
4.交易
再次強(qiáng)調(diào)的是,比特幣網(wǎng)絡(luò)中流轉(zhuǎn)的是交易信息,每個(gè)賬戶的余額是通過(guò)交易信息推算出來(lái)的,交易信息是雙向的,有一個(gè)輸入必定對(duì)應(yīng)一個(gè)輸出。
3.1交易輸入輸出
每一筆交易,out的總額應(yīng)該等于in的總額。但是,在這個(gè)交易單里,只會(huì)有out的Value,沒(méi)有in的Value,而是通過(guò)in的Pervious與index,追溯到上一個(gè)交易單的某一個(gè)out,獲得Value。
一次send bitcoin,剩下的錢(qián),應(yīng)該out給自己,否則這個(gè)錢(qián)就丟了。
情況列舉:
我有10個(gè)BTC,是某一次交易獲得的,我要送給朋友A,10個(gè)BTC。這時(shí)候,有一個(gè)in,一個(gè)out。
我有10個(gè)BTC,是某一次交易獲得的,我要送給朋友A,5個(gè)BTC,這時(shí)候,有一個(gè)in,兩個(gè)out,一個(gè)指向朋友5個(gè)BTC,一個(gè)指向我自己,得到剩下的5個(gè)BTC。
我有10個(gè)BTC,是以前的兩次交易獲得的,我要送給朋友A,10個(gè)BTC,這時(shí)候,有兩個(gè)in,一個(gè)out。
我有10個(gè)BTC,是以前的兩次交易獲得的,其中一次獲得了6個(gè)BTC,另一次獲得了4個(gè)BTC,我要送給我的朋友7個(gè)BTC,這時(shí)候,有兩個(gè)in,兩個(gè)out。
比特幣交易的基本單位是未經(jīng)使用的一個(gè)交易輸出,簡(jiǎn)稱UTXO。UTXO是不能再分割、被所有者鎖住或記錄于區(qū)塊鏈中的并被整個(gè)網(wǎng)絡(luò)識(shí)別成貨幣單位的一定量的比特幣貨幣。這句話什么意思呢?比特幣交易除了挖礦獲取以外,都是零和的,因?yàn)閰^(qū)塊鏈不維護(hù)余額信息也沒(méi)有余額概念,區(qū)塊鏈只有交易信息。舉個(gè)例子,你有10個(gè)比特幣現(xiàn)在需要支付2個(gè)出去,那么交易數(shù)據(jù)維護(hù)的是一個(gè)輸入(未經(jīng)使用的10個(gè)比特幣)和2個(gè)輸出(一個(gè)是2個(gè)幣對(duì)應(yīng)的地址),還有一個(gè)是8個(gè)幣對(duì)應(yīng)地址是你自己的地址。
3.2交易過(guò)程
交易的基本訴求,是付款人(payer)匯款給收款人(payee)。技術(shù)挑戰(zhàn)是加密(cryptography),目的是不讓第三者截獲甚至篡改匯款金額。
下圖解釋了 Owner0 給 Owner1以及后續(xù) 匯款的交易機(jī)制,截圖如下。

1. Owner0 先查到 Owner1 的公鑰。用 Owner1 的公鑰(Public Key)把匯款詳情加密。這樣,只有 Owner1 本人用自己的私鑰(Private Key),才能打開(kāi)加了密的匯款詳情。在圖例中,沒(méi)有畫(huà)匯款詳情。不過(guò)這個(gè)小小的敘述的疏忽無(wú)妨大雅。
2. 為了方便 Owner1 驗(yàn)證這筆匯款的確來(lái)自 Owner0,而不是別人,Owner0 發(fā)出的匯款單里,除了有加了密的匯款詳情,還有 Owner0 的數(shù)字簽名(Signature)。Owner1 拿到匯款時(shí),為了驗(yàn)證這筆匯款的確來(lái)自 Owner0,他可以用 Owner0 的公鑰,來(lái)驗(yàn)證匯款單中 Owner0 的數(shù)字簽名。
3. Owner0 發(fā)出匯款單時(shí),匯款單不僅僅投遞到 Owner1,而且還要廣而告之,任何人只要愿意參與 BitCoin 審計(jì),都可以收到全球所有人發(fā)出的所有匯款單。
4. 沿用 1、2、3 的原理,Owner1 給 Owner2 匯款,然后 Owner2 給 Owner3 匯款。BitCoin 通過(guò) Hash 機(jī)制,把涉及同一枚 BitCoin 的所有匯款交易(Tranaction)串連起來(lái),目的是為了追查重復(fù)付款(double spending)的欺詐行為。
單獨(dú)來(lái)看交易創(chuàng)建過(guò)程:

收款方對(duì)交易進(jìn)行驗(yàn)證:

4.挖礦原理
挖礦的本質(zhì)意義是挖礦節(jié)點(diǎn)爭(zhēng)奪記賬權(quán)!主觀上來(lái)說(shuō),挖礦節(jié)點(diǎn)獲得了挖礦獎(jiǎng)勵(lì)及交易費(fèi),客觀上來(lái)說(shuō),這保證了區(qū)塊鏈按照特定規(guī)則持續(xù)穩(wěn)定的被維護(hù)。
挖礦的具體實(shí)現(xiàn)就是在難度一定的情況下通過(guò)暴力雙SHA256哈希運(yùn)算獲取滿足難度taget的Nonce值,所謂的工作量證明就是無(wú)數(shù)次哈希運(yùn)算窮舉并比對(duì)的過(guò)程。
“挖礦”算法我們可以參考區(qū)塊頭結(jié)構(gòu)解說(shuō)如下:

第一步:找到區(qū)塊版本號(hào)version。
第二步:找到上一個(gè)區(qū)塊的hash值(父區(qū)塊哈希值):prev_hash。
第三步:輸入記錄交易的hash樹(shù)的根節(jié)點(diǎn)hash值(Merkle根):root_hash。
第四步:更新的時(shí)間(時(shí)間戳):time。
第五步:全網(wǎng)當(dāng)前難度(難度目標(biāo)):difficulty
針對(duì)難度目標(biāo)需要說(shuō)明:
難度在區(qū)塊中以“尾數(shù)-指數(shù)”的格式,編碼并存儲(chǔ),這種格式稱作“難度位”。這種編碼的首字節(jié)表示指數(shù),后面的3字節(jié)表示尾數(shù)(系數(shù))。以區(qū)塊277316為例,難度位的值為0x1903a30c,0x19是指數(shù)(exponent)的十六進(jìn)制格式,后半部0x03a30c是系數(shù)(coefficient)。
第六步:自己找一個(gè)隨機(jī)數(shù)Nonce:這個(gè)就是反復(fù)試的部分,不斷遞增該數(shù)字并做哈希運(yùn)算直到對(duì)應(yīng)哈希值小于難度指定的taget值。
把以上6個(gè)參數(shù)作為輸入,做二次SHA256運(yùn)算,形似于
SHA256(SHA256(version , prev_hash , root_hash , time , difficulty, random))
最終得到結(jié)果result。最后把結(jié)果result提交給系統(tǒng),由系統(tǒng)判斷這個(gè)計(jì)算結(jié)果是否有效(result
target通過(guò)difficulty可以計(jì)算得到:
target = coefficient * 2^(8 * (exponent – 3))
算法規(guī)定:一個(gè)新的區(qū)塊的第一筆交易必須將特定數(shù)目的比特幣發(fā)到某個(gè)地址,當(dāng)然這個(gè)地址肯定會(huì)設(shè)成挖礦人自己的比特幣地址,從而獲得系統(tǒng)的比特幣獎(jiǎng)勵(lì)。
5.總結(jié)
比特幣理論以密碼學(xué)為支撐,構(gòu)建了一個(gè)完備、安全、去中心化的數(shù)字貨幣體系,解決了數(shù)字資產(chǎn)所有權(quán)問(wèn)題、雙重支付問(wèn)題、現(xiàn)實(shí)世界的通貨膨脹問(wèn)題甚至還預(yù)留了機(jī)制使得構(gòu)建在資產(chǎn)轉(zhuǎn)移之上的智能合同成為可能。比特幣當(dāng)然是偉大的創(chuàng)造,期待比特幣有更好的未來(lái)。
另外,本書(shū)成文過(guò)程中參考了王秒等老師翻譯的《精通比特幣》,李鈞等老師的《比特幣》以及巴比特社區(qū)的大量知識(shí),感謝他們。
新聞熱點(diǎn)
疑難解答
圖片精選