〇、序言
貨幣由于其天然屬性決定了其與安全不可分割的聯(lián)系,從最早的金庫撵溃、保險柜疚鲤、鏢局到后來的ATM機(jī)、運鈔車缘挑;從存折到銀行卡集歇,從口令卡到優(yōu)盾,安全技術(shù)的進(jìn)步一步步推動著金融防護(hù)領(lǐng)域的更新语淘。
傳統(tǒng)的貨幣的安全需求诲宇,密碼學(xué)是安全手段,是從“可用”到“安心用”的升級惶翻。而對比特幣來說姑蓝,密碼學(xué)本身就是比特幣體系的一部分,沒有密碼學(xué)支撐的比特幣體系會完全崩塌吕粗,徹底“不可用”纺荧。本質(zhì)上來說,比特幣和密碼學(xué)是融為一體的颅筋,比特幣是自帶安全屬性的數(shù)字貨幣宙暇。因此,對比特幣用戶來說议泵,了解比特幣背后的密碼學(xué)理論占贫,有助于更好的理解比特幣;同時先口,通過密碼學(xué)理論的分享型奥,也可以順便感受一下人類智慧的偉大。畢竟碉京,在我眼里厢汹,密碼學(xué)理論是大量聰慧的頭腦審慎思考的結(jié)果,精致而又巧妙之處比比皆是谐宙。
一烫葬、密碼學(xué)理論
比特幣本身并沒有創(chuàng)造新的密碼學(xué)成果,但比特幣利用現(xiàn)有密碼學(xué)成果構(gòu)建了一個令人驚奇的全新的數(shù)字貨幣世界:去中心化卧惜、區(qū)塊鏈厘灼、可編程貨幣等成果即使拋開比特幣本身而言也是值得贊賞的洞見。
首先咽瓷,現(xiàn)代密碼學(xué)理論的共識遵循“柯克霍夫原則”:
柯克霍夫原則由奧古斯特·柯克霍夫在19世紀(jì)提出:密碼系統(tǒng)應(yīng)該就算被所有人知道系統(tǒng)的運作步驟设凹,仍然是安全的。
這個是什么意思呢茅姜,拿鑰匙和鎖的例子來說闪朱,研制和生產(chǎn)鎖具(包括鑰匙)的工藝是完全公開的月匣,鎖具被攻破只有兩種可能:一是證明工藝有漏洞,不需要拿到原裝鑰匙也能打開奋姿。二是窮盡各種鑰匙可能锄开,在可接受的時間里能夠從概率意義上試出來(暴力破解)。
算法是公開的称诗,唯一需要保護(hù)的是密鑰萍悴,這是我們下文討論的基礎(chǔ)。
1.非對稱加密
先看對稱加密很好理解也符合直覺:
對稱加密:對同一份敏感數(shù)據(jù)寓免,加密解密密鑰是相同的癣诱。
非對稱加密呢:
非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對袜香,如果用公開密鑰對數(shù)據(jù)進(jìn)行加密撕予,只有用對應(yīng)的私有密鑰才能解密;如果用私有密鑰對數(shù)據(jù)進(jìn)行加密蜈首,那么只有用對應(yīng)的公開密鑰才能解密实抡。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法欢策。 非對稱加密算法實現(xiàn)機(jī)密信息交換的基本過程是:甲方生成一對密鑰并將其中的一把作為公用密鑰向其它方公開吆寨;得到該公用密鑰的乙方使用該密鑰對機(jī)密信息進(jìn)行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專用密鑰對加密后的信息進(jìn)行解密猬腰。
我們用一幅圖來說明:
在上文的非對稱加密部分鸟废,密鑰A就是公開密鑰(簡稱公鑰)猜敢,密鑰B就是私有密鑰(簡稱私鑰)姑荷。道理都懂,問題有意思在什么地方呢缩擂?非對稱加密方式下密鑰A和密鑰B是怎么找到的以及怎么實現(xiàn)的鼠冕?我們舉例說明:
假設(shè)我們現(xiàn)在已經(jīng)找到了(具體怎么找的后面會講)公鑰(3233,17)和私鑰(3233, 2753)。
注意胯盯,公鑰和私鑰不一定只有一個數(shù)字懈费,是可以有多個的,具體幾個數(shù)字依賴于非對稱加密算法博脑。
假設(shè)現(xiàn)在明文待加密信息是數(shù)字65憎乙,我們首先給出加密公式:
解釋一下,c代表加密后數(shù)字叉趣,(n泞边,e)對應(yīng)我們的公鑰對,m代表明文疗杉,≡的意思是同模運算阵谚,比如60≡4(mod 7),60對4取模后等于4。好了我們開始計算密文:
密文是2790,如何解密呢梢什,解密公式:
d對應(yīng)私鑰的2753奠蹬,其余字母和加密過程相同,于是解密運算為:
我們得到了原來的明文數(shù)據(jù)65嗡午,這個例子可以看到加密和解密數(shù)據(jù)是不同的囤躁。
以上我們舉例使用的算法是大名鼎鼎的地球主流非對稱加密算法RSA,有關(guān)RSA的介紹參考阮一峰老師的文章荔睹。實際上我上面用到的數(shù)字也出自該文割以,實在是時間有限無法深入講解RSA的細(xì)節(jié)大家可以自行學(xué)習(xí)。比特幣體系實際使用的非對稱算法是橢圓曲線加密(ECC)应媚,可以到這里詳細(xì)了解严沥。
從上面的例子我們知道滿足非對稱加密的密鑰對是存在的,同時我們也做了加解密嘗試中姜。實際上消玄,非對稱加密算法的核心依賴于特定的數(shù)學(xué)難題,比如上文的RSA依賴于大數(shù)分解難題丢胚,如果該難題被破解了翩瓜,算法本身也就被攻破了。另外携龟,我讀研的時候還做了RSA矩陣擴(kuò)展兔跌,將其算法基礎(chǔ)從素數(shù)擴(kuò)展到矩陣,有興趣的可以繼續(xù)交流峡蟋。
非對稱算法通過公私鈅分別加解密方式給信息交換帶來了巨大的變化坟桅,具體表現(xiàn)在:
1)在不安全的環(huán)境中傳遞敏感信息成為可能。從上文可以知道蕊蝗,公鑰是完全公開任意傳播的仅乓,通過公鑰是無法(或極其困難)推算出私鑰的,私鑰是不公開不發(fā)送不傳播的蓬戚,僅僅消息接收方知道就可以夸楣,其他任何人都不需要知道。
2)多方通信所需密鑰數(shù)量急劇減少子漩,密鑰維護(hù)工作變得異常簡化豫喧。比如N個互不信任且互有通信需求的人,如果使用對稱加密算法幢泼,則需要N紧显!/2個密鑰,如果使用非對稱加密僅需要N個即可(每個人只需要維護(hù)自己的公私鈅對旭绒,無論和多少人通信)鸟妙。
3)基于非對稱加密發(fā)展起來的數(shù)字簽名技術(shù)(見下文詳述)從數(shù)學(xué)意義上解決了自證身份問題焦人,使得信息接收者可以確認(rèn)消息發(fā)送方身份信息且不可更改。
4)密碼學(xué)問題對數(shù)學(xué)問題的依賴空前提高重父。之前看似無用的甚至古老的數(shù)學(xué)難題比如數(shù)論花椭、離散對數(shù)等在此大放異彩,頗有些笑來老師在《把時間當(dāng)做朋友》里面表達(dá)的"技不壓身"的現(xiàn)實映射房午。
2.散列(哈希)算法
我們使用各種云盤矿辽、虛擬存儲空間應(yīng)用的時候一定都有類似的體會,上傳一個明明很大的文件郭厌,可是速度卻非炒螅快,而有時上傳一個小得多的文件卻似乎進(jìn)度條要走很久折柠。這種現(xiàn)象的可能的一個秘密就是接下來要講的散列算法(也叫數(shù)據(jù)摘要或者哈希算法宾娜,哈希是HASH的音譯)。
實際上扇售,云盤類產(chǎn)品對相同文件只會保留一份真實的存儲前塔,多個使用相同文件的用戶只需“索引”到該存儲位置即可。判斷兩個文件是否相同用到的就是散列算法:
散列算法將任意長度的二進(jìn)制值映射為較短的固定長度的二進(jìn)制值承冰,這個小的二進(jìn)制值稱為哈希值华弓。哈希值是一段數(shù)據(jù)唯一且極其緊湊的數(shù)值表示形式。如果散列一段明文而且哪怕只更改該段落的一個字母困乒,隨后的散列值都將產(chǎn)生不同的值寂屏。要找到散列為同一個值的兩個不同的輸入,在計算上是不可能的娜搂,所以數(shù)據(jù)的散列值可以檢驗數(shù)據(jù)的完整性迁霎。一般用于快速查找和加密算法。
本質(zhì)上涌攻,散列算法的目的不是為了“加密”而是為了抽取“數(shù)據(jù)特征”欧引,你也可以把給定數(shù)據(jù)的散列值理解為該數(shù)據(jù)的“指紋信息”频伤,一個可靠的散列算法F需要滿足:
1. 對于給定的數(shù)據(jù)M恳谎,很容易算出哈希值X=F(M);
2. 根據(jù)X無法算出M憋肖;
3. 很難找到M和N令F(M)=F(N)因痛。
我來解釋一下:
對于第一點,通常哈希值的長度是固定的(為什么固定岸更,一個很重要的原因是便于構(gòu)造通信包結(jié)構(gòu)鸵膏,散列的應(yīng)用場景通常是不可靠的網(wǎng)絡(luò)傳輸而非本地存儲),比如比特幣使用的SHA256摘要算法對任意長度的輸入給出的是256bit的輸出怎炊。
對于第二點谭企,散列算法是不可逆的廓译,甚至是以丟失部分原始信息作為代價,因此我個人認(rèn)為散列加密算法的提法是有問題的债查,加密意味著可以解密非区,單純的擾亂稱為加密并不合適。也許所謂的散列加密是和散列校驗對應(yīng)的盹廷,也就說兩種應(yīng)用的場景不同征绸,散列加密的核心是擾亂,散列校驗的核心是校驗俄占。
對于第三點管怠,這是散列函數(shù)真正的挑戰(zhàn)。假設(shè)找到了一對(M,N)使得等式成立就成為該算法找到了一次碰撞缸榄,對散列算法健壯性的分析就是分析其抗強(qiáng)碰撞能力渤弛。可以理解的是甚带,碰撞的出現(xiàn)將使得散列算法本身存在的意義消失了暮芭,因為發(fā)現(xiàn)了不同的人擁有相同的指紋。
比特幣使用的散列算法是SHA256欲低,他是安全散列算法SHA(Secure Hash Algorithm)系列算法的一種(另外還有SHA-1辕宏、SHA-224、SHA-384 和 SHA-512 等變體)砾莱,SHA是美國國家安全局 (NSA) 設(shè)計瑞筐,美國國家標(biāo)準(zhǔn)與技術(shù)研究院(NIST) 發(fā)布的,主要適用于數(shù)字簽名標(biāo)準(zhǔn)(DigitalSignature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA)腊瑟【奂伲可以到這里詳細(xì)了解。
最后闰非,我要解釋一下二次散列問題膘格,看過比特幣協(xié)議的讀者可能注意到工作量證明和密鑰編碼過程中多次使用了二次哈希,如SHA256(SHA256(k))或者RIPEMD160(SHA256(K))财松,這種方式帶來的好處是增加了工作量或者在不清楚協(xié)議的情況下增加破解難度瘪贱,從安全性角度并沒有顯著增加(如果是暴力窮舉破解的話,需要增加一倍破解時間)辆毡。真正的二次哈希是基于加鹽的哈希菜秦,什么意思呢?對于特定的待散列數(shù)據(jù)和特定的散列算法舶掖,可以知道散列值是一定的球昨,這種情況下如果用散列保護(hù)敏感數(shù)據(jù)(理論上是不合適的,但是國內(nèi)外存在大量的使用散列來保護(hù)用戶密碼的情況)眨攘,那就很容易使用字典攻擊反向推算主慰,比如我計算123456的SHA256值就可以反推了嚣州,解決辦法就是先做一次散列,再加一次隨機(jī)數(shù)據(jù)以后再做一次散列共螺,隨機(jī)數(shù)據(jù)就是所謂的鹽避诽。
3.數(shù)字簽名
有了非對稱加密和散列算法的準(zhǔn)備,我們現(xiàn)在可以進(jìn)一步認(rèn)識數(shù)字簽名了璃谨。顧名思義沙庐,數(shù)字簽名就是在數(shù)字世界里用于身份辨識的一種解決方案。不需要騎縫章佳吞,騎縫簽名拱雏,也不需要筆跡專家,數(shù)字簽名即具有不可抵賴性底扳。
簡單地說,所謂數(shù)字簽名就是附加在數(shù)據(jù)單元上的一些數(shù)據(jù),或是對數(shù)據(jù)單元所作的密碼變換铸抑。這種數(shù)據(jù)或變換允許數(shù)據(jù)單元的接收者用以確認(rèn)數(shù)據(jù)單元的來源和數(shù)據(jù)單元的完整性并保護(hù)數(shù)據(jù),防止被人(例如接收者)進(jìn)行偽造。它是對電子形式的消息進(jìn)行簽名的一種方法,一個簽名消息能在一個通信網(wǎng)絡(luò)中傳輸衷模∪笛矗基于公鑰密碼體制和私鑰密碼體制都可以獲得數(shù)字簽名,主要是基于公鑰密碼體制的數(shù)字簽名。
上述解釋稍顯學(xué)術(shù)阱冶,我們換種說法表述:所謂數(shù)字簽名就是簽名人用自己的私鑰對待簽名數(shù)據(jù)的摘要進(jìn)行加密得到的值就是簽名值刁憋。簽名者發(fā)送數(shù)據(jù)簽名時需要把待簽名數(shù)據(jù)和簽名值一起發(fā)送給對方。
注意木蹬,簽名對象并非待簽名數(shù)據(jù)而是待簽名數(shù)據(jù)的摘要至耻,為什么呢?因為非對稱加密的速度通常都比較慢镊叁,直接對原始數(shù)據(jù)私鑰加密是很慢的而且也沒有必要尘颓。
如何驗證簽名呢?接收方首先使用簽名者的公鑰對簽名值解密即可得到摘要值晦譬,然后使用約定的算法對待簽名數(shù)據(jù)進(jìn)行散列運算后和解密得到的摘要值進(jìn)行比較即可驗證疤苹。
這里有一個圖形化的數(shù)字簽名過程有助于理解數(shù)字簽名的整個過程。
從以上數(shù)字簽名的整個過程描述來看敛腌,數(shù)字簽名的核心在于簽名卧土,在于證明這份數(shù)據(jù)是簽名者發(fā)出的、不可抵賴的迎瞧。待簽名數(shù)據(jù)本身的保密不是數(shù)字簽名方案要考慮的問題夸溶。
4.可讀性編碼
嚴(yán)格來講,編碼部分不是密碼學(xué)理論的核心內(nèi)容凶硅,不過為了便于下文能說清楚未巫,我就把可讀性編碼放到這里簡單說說跌造。
可讀性編碼很好理解逃糟,就是不改變信息內(nèi)容僅改變內(nèi)容的表現(xiàn)形式笆焰,部分編碼方式還加入了容錯校驗功能,通常是為了保證更好的通信傳輸氢妈。
比如二進(jìn)制的1111對應(yīng)十進(jìn)制的15這就是一次編碼粹污。是用十進(jìn)制對二進(jìn)制進(jìn)行編碼,現(xiàn)在有個問題首量,我拿到一個編碼后的數(shù)據(jù)壮吩,如何知道該數(shù)據(jù)是使用了哪種形式的編碼呢?這個是通過前綴來實現(xiàn)的加缘,例如鸭叙,比特幣地址的前綴是0(十六進(jìn)制是0x00),而對私鑰編碼時前綴是128(十六進(jìn)制是0x80)拣宏。
二沈贝、比特幣實踐
從現(xiàn)在開始,我們開始真刀實槍了勋乾,先看看比特幣的編碼世界宋下。
1.Base58和Base58Check編碼
這里請允許我拿來主義,我覺得王秒等多位老師翻譯的Andreas M. Antonopoulos所著《精通比特幣》對這個問題已經(jīng)解釋的很清楚了辑莫,更詳細(xì)的描述還可以看看這里学歧。
為了更簡潔方便地表示長串的數(shù)字,許多計算機(jī)系統(tǒng)會使用一種以數(shù)字和字母組成的大于十進(jìn)制的表示法各吨。例如撩满,傳統(tǒng)的十進(jìn)制計數(shù)系統(tǒng)使用0-9十個數(shù)字,而十六進(jìn)制系統(tǒng)使用了額外的 A-F 六個字母绅你。一個同樣的數(shù)字伺帘,它的十六進(jìn)制表示就會比十進(jìn)制表示更短。更進(jìn)一步忌锯,Base64使用了26個小寫字母伪嫁、26個大寫字母、10個數(shù)字以及兩個符號(例如“+”和“/”)偶垮,用于在電子郵件這樣的基于文本的媒介中傳輸二進(jìn)制數(shù)據(jù)张咳。Base64通常用于編碼郵件中的附件。Base58是一種基于文本的二進(jìn)制編碼格式似舵,用在比特幣和其它的加密貨幣中脚猾。這種編碼格式不僅實現(xiàn)了數(shù)據(jù)壓縮,保持了易讀性砚哗,還具有錯誤診斷功能龙助。Base58是Base64編碼格式的子集,同樣使用大小寫字母和10個數(shù)字蛛芥,但舍棄了一些容易錯讀和在特定字體中容易混淆的字符提鸟。具體地军援,Base58不含Base64中的0(數(shù)字0)、O(大寫字母o)称勋、l(小寫字母L)胸哥、I(大寫字母i),以及“+”和“/”兩個字符赡鲜。簡而言之空厌,Base58就是由不包括(0,O银酬,l嘲更,I)的大小寫字母和數(shù)字組成。
需要注意的是捡硅,Base58編碼是不含校驗信息的哮内,Base58Check是一種常用在比特幣中的Base58編碼格式,增加了錯誤校驗碼來檢查數(shù)據(jù)在轉(zhuǎn)錄中出現(xiàn)的錯誤壮韭。校驗碼長4個字節(jié)北发,添加到需要編碼的數(shù)據(jù)之后。
為了使用Base58Check編碼格式對數(shù)據(jù)(數(shù)字)進(jìn)行編碼喷屋,首先我們要對數(shù)據(jù)添加一個稱作“版本字節(jié)”的前綴琳拨,這個前綴用來明確需要編碼的數(shù)據(jù)的類型。例如屯曹,比特幣地址的前綴是0(十六進(jìn)制是0x00)狱庇,而對私鑰編碼時前綴是128(十六進(jìn)制是0x80)。 表4-1會列出一些常見版本的前綴恶耽。
接下來密任,我們計算“雙哈希”校驗碼偷俭,意味著要對之前的結(jié)果(前綴和數(shù)據(jù))運行兩次SHA256哈希算法:
checksum = SHA256(SHA256(prefix+data))
在產(chǎn)生的長32個字節(jié)的哈希值(兩次哈希運算)中浪讳,我們只取前4個字節(jié)。這4個字節(jié)就作為校驗碼涌萤。校驗碼會添加到數(shù)據(jù)之后淹遵。結(jié)果由三部分組成:前綴、數(shù)據(jù)和校驗碼负溪。
2.密鑰透揣、地址與錢包
先說結(jié)論:
1.密鑰通常指的是保護(hù)比特幣資產(chǎn)的對應(yīng)于所有權(quán)用戶的私鑰,個別時候也會模糊的統(tǒng)稱私鑰和公鑰為密鑰川抡,這里我們以狹義的私鑰解釋為準(zhǔn)辐真。
2.地址大部分情況下是指對公鑰的封裝(個別時候除了公鑰還有腳本)。
3.錢包是私鑰的容器,通常通過有序文件或者簡單的數(shù)據(jù)庫實現(xiàn)拆祈。比特幣錢包包含私鑰和公鑰數(shù)據(jù)恨闪,盡管公鑰數(shù)據(jù)理論是是不需要存儲的倘感。
2.1私鑰保護(hù)
私鑰必須保密放坏。私鑰的機(jī)密性需求事實情況是,在實踐中相當(dāng)難以實現(xiàn)老玛,因為該需求與同樣重要的安全對象可用性相互矛盾淤年。當(dāng)你需要為了避免私鑰丟失而存儲備份時,會發(fā)現(xiàn)維護(hù)私鑰私密性是一件相當(dāng)困難的事情蜡豹。通過密碼加密內(nèi)有私鑰的錢包可能要安全一點麸粮,但那個錢包也需要備份。有時镜廉,例如用戶因為要升級或重裝錢包軟件弄诲,而需要把密鑰從一個錢包轉(zhuǎn)移到另一個。私鑰備份也可能需要存儲在紙張上(參見“4.5.4 紙錢包”一節(jié))或者外部存儲介質(zhì)里娇唯,比如U盤齐遵。但如果一旦備份文件失竊或丟失呢?這些矛盾的安全目標(biāo)推進(jìn)了便攜塔插、方便梗摇、可以被眾多不同錢包和比特幣客戶端理解的加密私鑰標(biāo)準(zhǔn)BIP0038的出臺。
BIP0038提出了一個通用標(biāo)準(zhǔn)想许,使用一個口令加密私鑰并使用Base58Check對加密的私鑰進(jìn)行編碼伶授,這樣加密的私鑰就可以安全地保存在備份介質(zhì)里,安全地在錢包間傳輸流纹,保持密鑰在任何可能被暴露情況下的安全性糜烹。這個加密標(biāo)準(zhǔn)使用了AES,這個標(biāo)準(zhǔn)由NIST建立漱凝,并廣泛應(yīng)用于商業(yè)和軍事應(yīng)用的數(shù)據(jù)加密疮蹦。
2.2公鑰與地址
我們知道比特幣協(xié)議的區(qū)塊鏈實際上是對交易的維護(hù)而不是對賬戶的維護(hù),交易數(shù)據(jù)本身并不需要私鑰碉哑,因此對公鑰的封裝也就是地址就顯得格外重要挚币,需要兼顧安全,效率和擴(kuò)展扣典。
從公鑰到地址經(jīng)歷了如下過程:
A = RIPEMD160(SHA256(K))
公式中妆毕,K是公鑰,A是生成的比特幣地址贮尖。比特幣地址與公鑰不同笛粘。比特幣地址是由公鑰經(jīng)過單向的哈希函數(shù)生成的
以公鑰 K 為輸入,計算其SHA256哈希值,并以此結(jié)果計算RIPEMD160 哈希值薪前,得到一個長度為160比特(20字節(jié))的數(shù)字后進(jìn)行Base58Check編碼即可得到比特幣地址润努。從編碼數(shù)據(jù)結(jié)構(gòu)的視角看,是下圖:
需要注意的是示括,從地址已經(jīng)無法反推公鑰信息铺浇,因此,需要將私鑰以及對應(yīng)的公鑰垛膝、地址一起存儲鳍侣。
2.3比特幣錢包
比特幣錢包要解決的核心問題是私鑰管理,早期的方式是隨機(jī)生成私鑰池并一次一密吼拥,這當(dāng)然是安全性很高的方案倚聚。但是對存儲,導(dǎo)入導(dǎo)出備份帶來了極大的挑戰(zhàn)凿可,畢竟私鑰丟了誰也沒有辦法惑折。改進(jìn)的私鑰管理辦法將私鑰鏈?zhǔn)焦芾砥饋砹耍娤聢D:
生成鏈?zhǔn)浇Y(jié)構(gòu)的過程如下:
3.區(qū)塊鏈
區(qū)塊鏈可以理解為數(shù)據(jù)結(jié)構(gòu)概念中的鏈表(和線性表略有不同的是可能有分叉)枯跑,這里我們只需要大致了解區(qū)塊數(shù)據(jù)結(jié)構(gòu)以及每一塊大致的意思惨驶,這些結(jié)構(gòu)信息將會在交易和挖礦部分進(jìn)行詳細(xì)講解。
區(qū)塊鏈可以理解為運行在去中心化網(wǎng)絡(luò)中的全肮,所有節(jié)點(挖礦節(jié)點)共同維護(hù)的交易數(shù)據(jù)庫敞咧,這個數(shù)據(jù)庫是以鏈?zhǔn)降男问浇M織交易數(shù)據(jù)的,每一個鏈表的塊被稱為區(qū)塊或者block辜腺。
3.1 區(qū)塊結(jié)構(gòu)
區(qū)塊是一種被包含在公開賬簿(區(qū)塊鏈)里的聚合了交易信息的容器數(shù)據(jù)結(jié)構(gòu)休建。它由一個包含元數(shù)據(jù)的區(qū)塊頭和緊跟其后的構(gòu)成區(qū)塊主體的一長串交易組成。
上表中的1-9應(yīng)該是1-9個字節(jié)评疗,否則會引起歧義测砂。
3.2 區(qū)塊頭
區(qū)塊頭由三組區(qū)塊元數(shù)據(jù)組成。首先是一組引用父區(qū)塊哈希值的數(shù)據(jù)百匆,這組元數(shù)據(jù)用于將該區(qū)塊與區(qū)塊鏈中前一區(qū)塊相連接砌些。第二組元數(shù)據(jù),即難度加匈、時間戳和nonce存璃,與挖礦競爭相關(guān)。第三組元數(shù)據(jù)是merkle樹根(一種用來有效地總結(jié)區(qū)塊中所有交易的數(shù)據(jù)結(jié)構(gòu))雕拼。
Nonce纵东、難度目標(biāo)和時間戳?xí)糜谕诘V過程,Merkle根用來索引和組織該區(qū)塊所有的交易信息啥寇,其結(jié)構(gòu)見下一節(jié)偎球。
因此區(qū)塊頭之間的連接大約像下圖所示:
從上圖我們可以知道如何避免雙重支付問題洒扎,因為收款人有辦法對這筆支付之前的所有消息進(jìn)行檢索直至追溯到原始的挖礦區(qū)塊袍冷,實際上比特幣世界里的每一枚比特幣都是被標(biāo)記可溯源猫牡,雙重支付是可以避免的。
3.3 Merkle Tree
Merkle Tree镊掖,是一種樹(數(shù)據(jù)結(jié)構(gòu)中所說的樹)褂痰,網(wǎng)上大都稱為Merkle Hash Tree,這是因為 它所構(gòu)造的Merkle Tree的所有節(jié)點都是Hash值。Merkle Tree具有以下特點:
1. 它是一種樹缩歪,可以是二叉樹,也可以多叉樹匪蝙,無論是幾叉樹主籍,它都具有樹結(jié)構(gòu)的所有特點;
2. Merkle樹的葉子節(jié)點上的value逛球,是由你指定的千元,這主要看你的設(shè)計了,如Merkle Hash Tree會將數(shù)據(jù)的Hash值作為葉子節(jié)點的值颤绕;
3 非葉子節(jié)點的value是根據(jù)它下面所有的葉子節(jié)點值幸海,然后按照一定的算法計算而得出的。如Merkle Hash Tree的非葉子節(jié)點value的計算方法是將該節(jié)點的所有子節(jié)點進(jìn)行組合奥务,然后對組合結(jié)果進(jìn)行hash計算所得出的hash value物独。
例如,下圖就是一個Merkle Hash Tree形狀氯葬,如果它是Merkle Hash Tree挡篓,則節(jié)點7的hash value必須是通過節(jié)點15、16上的value計算而得到.
在處理比對或驗證的應(yīng)用場景中時帚称,特別是在分布式環(huán)境下進(jìn)行比對或驗證時官研,Merkle Tree會大大減少數(shù)據(jù)的傳輸量以及計算的復(fù)雜度。例如闯睹,就拿圖一舉例戏羽,假如是 15,16.......30是一個個數(shù)據(jù)塊的hash值,我把這些數(shù)據(jù)從A傳輸?shù)紹瞻坝,數(shù)據(jù)傳輸?shù)紹后蛛壳,我想驗證下傳輸?shù)紹上的數(shù)據(jù)的有效性型(驗證數(shù)據(jù)是否在傳輸過程中發(fā)生變化)杏瞻,只需要驗證A 和 B上所構(gòu)造的Merkle
Tree的root節(jié)點值是否一致即可,如果一致衙荐,表示數(shù)據(jù)是有效的捞挥,傳輸過程中沒有發(fā)生改變。假如在傳輸過程中忧吟,15對應(yīng)的數(shù)據(jù)被人篡改溜族,通過Merkle Tree很容易定位找到(因為此時,節(jié)點0,1,3,7,15對應(yīng)的hash值都發(fā)生了變化)
需要解釋的是交易數(shù)據(jù)是怎么構(gòu)建成數(shù)的呢仍劈,其實很簡單:首先將所有交易作為葉子節(jié)點,兩兩相鄰分組(總的交易數(shù)量如果是奇數(shù)就把單個的那個復(fù)制一份)况既,然后對每一對交易分別計算哈希并依此向上構(gòu)建樹直至根節(jié)點悲靴,如下圖所示:
4.交易
再次強(qiáng)調(diào)的是癞尚,比特幣網(wǎng)絡(luò)中流轉(zhuǎn)的是交易信息否纬,每個賬戶的余額是通過交易信息推算出來的临燃,交易信息是雙向的膜廊,有一個輸入必定對應(yīng)一個輸出爪瓜。
3.1交易輸入輸出
每一筆交易,out的總額應(yīng)該等于in的總額铆铆。但是,在這個交易單里,只會有out的Value,沒有in的Value,而是通過in的Pervious與index,追溯到上一個交易單的某一個out,獲得Value薄货。
一次send bitcoin,剩下的錢,應(yīng)該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瞎抛。
比特幣交易的基本單位是未經(jīng)使用的一個交易輸出桐臊,簡稱UTXO断凶。UTXO是不能再分割、被所有者鎖住或記錄于區(qū)塊鏈中的并被整個網(wǎng)絡(luò)識別成貨幣單位的一定量的比特幣貨幣介汹。這句話什么意思呢窗价?比特幣交易除了挖礦獲取以外撼港,都是零和的帝牡,因為區(qū)塊鏈不維護(hù)余額信息也沒有余額概念否灾,區(qū)塊鏈只有交易信息墨技。舉個例子断楷,你有10個比特幣現(xiàn)在需要支付2個出去冬筒,那么交易數(shù)據(jù)維護(hù)的是一個輸入(未經(jīng)使用的10個比特幣)和2個輸出(一個是2個幣對應(yīng)的地址)舞痰,還有一個是8個幣對應(yīng)地址是你自己的地址响牛。
3.2交易過程
交易的基本訴求呀打,是付款人(payer)匯款給收款人(payee)贬丛。技術(shù)挑戰(zhàn)是加密(cryptography)豺憔,目的是不讓第三者截獲甚至篡改匯款金額焕阿。
下圖解釋了 Owner0 給 Owner1以及后續(xù) 匯款的交易機(jī)制,截圖如下毅桃。
1. Owner0 先查到 Owner1 的公鑰。用 Owner1 的公鑰(Public Key)把匯款詳情加密衫嵌。這樣楔绞,只有 Owner1 本人用自己的私鑰(Private Key)酒朵,才能打開加了密的匯款詳情蔫耽。在圖例中,沒有畫匯款詳情碍粥。不過這個小小的敘述的疏忽無妨大雅即纲。
2. 為了方便 Owner1 驗證這筆匯款的確來自 Owner0,而不是別人膊畴,Owner0 發(fā)出的匯款單里病游,除了有加了密的匯款詳情买猖,還有 Owner0 的數(shù)字簽名(Signature)玉控。Owner1 拿到匯款時高诺,為了驗證這筆匯款的確來自 Owner0虱而,他可以用 Owner0 的公鑰牡拇,來驗證匯款單中 Owner0 的數(shù)字簽名导俘。
3. Owner0 發(fā)出匯款單時罢杉,匯款單不僅僅投遞到 Owner1赋秀,而且還要廣而告之猎莲,任何人只要愿意參與 BitCoin 審計技即,都可以收到全球所有人發(fā)出的所有匯款單而叼。
4. 沿用 1液荸、2娇钱、3 的原理文搂,Owner1 給 Owner2 匯款,然后 Owner2 給 Owner3 匯款。BitCoin 通過 Hash 機(jī)制然遏,把涉及同一枚 BitCoin 的所有匯款交易(Tranaction)串連起來,目的是為了追查重復(fù)付款(double spending)的欺詐行為秧倾。
單獨來看交易創(chuàng)建過程:
收款方對交易進(jìn)行驗證:
4.挖礦原理
挖礦的本質(zhì)意義是挖礦節(jié)點爭奪記賬權(quán)!主觀上來說售淡,挖礦節(jié)點獲得了挖礦獎勵及交易費,客觀上來說汤纸,這保證了區(qū)塊鏈按照特定規(guī)則持續(xù)穩(wěn)定的被維護(hù)贮泞。
挖礦的具體實現(xiàn)就是在難度一定的情況下通過暴力雙SHA256哈希運算獲取滿足難度taget的Nonce值啃擦,所謂的工作量證明就是無數(shù)次哈希運算窮舉并比對的過程议惰。
“挖礦”算法我們可以參考區(qū)塊頭結(jié)構(gòu)解說如下:
第一步:找到區(qū)塊版本號version俯萎。
第二步:找到上一個區(qū)塊的hash值(父區(qū)塊哈希值):prev_hash夫啊。
第三步:輸入記錄交易的hash樹的根節(jié)點hash值(Merkle根):root_hash报嵌。
第四步:更新的時間(時間戳):time锚国。
第五步:全網(wǎng)當(dāng)前難度(難度目標(biāo)):difficulty
針對難度目標(biāo)需要說明:
難度在區(qū)塊中以“尾數(shù)-指數(shù)”的格式绘沉,編碼并存儲,這種格式稱作“難度位”豺总。這種編碼的首字節(jié)表示指數(shù)车伞,后面的3字節(jié)表示尾數(shù)(系數(shù))。以區(qū)塊277316為例喻喳,難度位的值為0x1903a30c另玖,0x19是指數(shù)(exponent)的十六進(jìn)制格式,后半部0x03a30c是系數(shù)(coefficient)表伦。
第六步:自己找一個隨機(jī)數(shù)Nonce:這個就是反復(fù)試的部分谦去,不斷遞增該數(shù)字并做哈希運算直到對應(yīng)哈希值小于難度指定的taget值。
把以上6個參數(shù)作為輸入哪轿,做二次SHA256運算飘痛,形似于
SHA256(SHA256(version , prev_hash , root_hash , time , difficulty, random))
最終得到結(jié)果result塑猖。最后把結(jié)果result提交給系統(tǒng)蜡励,由系統(tǒng)判斷這個計算結(jié)果是否有效(result<target為有效)扮碧。若判定結(jié)果為有效,你就產(chǎn)生了一個新的區(qū)塊,并會告知全網(wǎng)。
target通過difficulty可以計算得到:
target = coefficient * 2^(8 * (exponent – 3))
算法規(guī)定:一個新的區(qū)塊的第一筆交易必須將特定數(shù)目的比特幣發(fā)到某個地址搂赋,當(dāng)然這個地址肯定會設(shè)成挖礦人自己的比特幣地址宋欺,從而獲得系統(tǒng)的比特幣獎勵掌挚。
5.總結(jié)
比特幣理論以密碼學(xué)為支撐,構(gòu)建了一個完備标捺、安全茂缚、去中心化的數(shù)字貨幣體系,解決了數(shù)字資產(chǎn)所有權(quán)問題扶踊、雙重支付問題车猬、現(xiàn)實世界的通貨膨脹問題甚至還預(yù)留了機(jī)制使得構(gòu)建在資產(chǎn)轉(zhuǎn)移之上的智能合同成為可能伏嗜。比特幣當(dāng)然是偉大的創(chuàng)造军熏,期待比特幣有更好的未來。
另外偷办,本書成文過程中參考了王秒等老師翻譯的《精通比特幣》详囤,李鈞等老師的《比特幣》以及巴比特社區(qū)的大量知識理澎,感謝他們。
最后凡壤,感謝大家和我一起參與這次分享,歡迎大家添加或掃描下面的二維碼加我的個人微信號 zbren_im繼續(xù)交流。