區塊鏈,成為這兩年最火的互聯網字眼,但估計大多數人都只是聽著耳熟,並不真正了解。
與區塊鏈一起出現最多的詞是比特幣,顯然,它們之間肯定存在某種緊密的關系。
本文是一篇深度介紹比特幣和區塊鏈知識的文章,我努力按照「自頂向下、逐次求精」的原則,將比特幣和區塊鏈知識像剝洋蔥一樣,一層一層地深入下去,讓讀者每剝下一層都有完整的知識收獲。
去中心化
本文圖片均來自「讀庫」微信公眾號
區塊鏈原本是一種基於互聯網的信息編碼、傳輸、加密、解密、驗證技術,但在我看來,現在已經上升到了一種「去中心化」的理念,本質上是一種理念上的革新。而比特幣就是這種理念的一個具體應用。
打個比方來說,區塊鏈就相當於電子商務,你想想二十年前有幾個人搞得懂什麽是電子商務,它本質上也是一種理念,只不過這種理念必須要借助一定的技術手段來實現。而比特幣就相當於淘寶網,是電子商務的一個具體應用。
所以,我們要理解什麽是區塊鏈,必須先理解什麽是去中心化。我舉兩個例子來幫助你理解:
第一個例子是從網上下載電影。最早的時候,我們下載電影都是到一些知名的電影下載網站,這些網站會把電影文件存放在一臺或者一組服務器上,大家都訪問這臺(組)服務器下載影片。這叫中心化。
在這個遊戲規則中,電影網站的服務器就是中心,每一個下載電影的人只不過是這個中心拉出來的線而已。中心化的遊戲中,玩家的地位是不平等的,網站主占據絕對強勢地位,他想讓你下載就下載,想給你限速就限速。
後來,一種去中心化的下載模式出現了,這就是BT下載,也叫P2P(peer to peer)下載。現在我們講到P2P,一般是指那種個人借貸的網站,但最初的概念是從BT下載來的,P2P就是個人到個人,點到點。BT下載的原理與電影網站完全不同,影片並不是存在某個服務器上,而是大家互相從網絡上的每一個人那里去下載這個影片的一小部分,最後拼成一個完整的文件。
在這個遊戲中,所有玩家的地位是完全平等的,任何一個玩家都可以隨時離場、隨時加入,只要還有人在玩,整個遊戲就能正常運行,沒有人擁有特別的權力。這就叫去中心化。
第二個例子,就是我們每天都在使用的銀行卡或者支付寶、微信這些人民幣支付手段,現金我們先拋開不談。我們用無現金的方式支付人民幣買東西,就是一個中心化的遊戲,它的中心有好多級,比如說,支付寶的服務器是第一級中心,支付寶資金的托管銀行如工商銀行、中信銀行的服務器就是第二級中心,這些銀行的再上一級中心就是央行——中國人民銀行的服務器。
在這個遊戲中,不同級別玩家的權力、地位是不平等的,最大的Boss當然是央行,它甚至能發行貨幣,它的權力可以大到分分鐘就把我們的錢全部搶光,很簡單,它只需要突然增發貨幣就可以了,物價突然上漲一百倍,我們的錢就等於被搶光了。那貨幣遊戲能不能像下載電影一樣去中心化呢?也是可以的,比特幣系統就是這樣一個去中心化的貨幣遊戲系統,你可以把它看成是一個大型的貨幣實驗。
比特幣的遊戲是這麽玩的,就兩條核心規則。第一,它的貨幣發行不是由某個機構說了算,而是公開一套算法,每算出一個符合要求的數字,就相當於挖到了若幹個比特幣。誰都可以去算,絕對公平,誰也作不了弊,因為算法本質上就是一個個數字去湊,湊出一個算一個。第二,比特幣的交易信息不是記在某一臺服務器上的,而是所有參與這個遊戲的玩家電腦中一人一份,同步記錄,這種交易記錄在理論上幾乎是無法篡改的。
這就是「去中心化賬本」。
這樣一來,所有遊戲玩家的地位和權力就完全平等了,幾乎沒有任何一個玩家是特殊的。為什麽要加上「幾乎」兩個字呢?因為,畢竟能夠有能力挖比特幣的那些礦主還是有點特殊的,但這種特殊性並不是太大,而且礦主也沒有任何壁壘,只要你買得起好電腦,誰都可以當礦主。
不得不說,比特幣的這個「去中心化」設計非常之妙。它的發明人,神秘的中本聰(Satoshi Nakamoto)確實是棵「大蔥」。
理解了去中心化,就等於理解了區塊鏈。一個真正的區塊鏈項目,就是通過合理的遊戲規則設計,輔以信息技術,來踐行去中心化理念的項目。比特幣系統就是去中心化理念和區塊鏈技術的一個優秀示範項目。
不誇張地說,我覺得這是一場互聯網的理念革命,是人類的又一次平等化革命。上一次革命是打破了人與人之間在身份地位上的不平等,這一次則是打破了遊戲規則本身的不平等。正因為這樣,區塊鏈才能激發人們如此大的熱情,這是一個聽上去可以顛覆一切舊規則的新生事物。
然而,在我看來,比特幣系統並不是一個成功的區塊鏈應用,甚至先天不足。為什麽這麽說呢?因為,看前面介紹的兩條比特幣核心遊戲規則就知道,它有以下這些天生的缺陷:
第一,比特幣客戶端軟件需要巨大無比的存儲空間,因為每一個節點都必須記錄下從比特幣系統誕生的第一天起所有的交易記錄,截止到本文寫作時(2018年2月13日),這個交易記錄文件已經有147GB那麽大了,而且只會增加不會減少。
第二,為防止有人作弊,比特幣系統有一套很復雜的遊戲規則來確保交易記錄是真實的,這樣就導致每一筆交易的確認時間一般需要一個小時甚至幾天。想想吧,如果用比特幣去街邊買杯奶茶,會是什麽情況。
第三,最多只有2100萬枚比特幣,而且,無論有多少人在挖礦,系統規則決定了平均每十分鐘才能產出若幹枚比特幣(2018年是每十分鐘12.5枚)。矛盾正如那句話:人民群眾日益增長的比特幣需求與比特幣總量不足之間的矛盾。
比特幣不能代表區塊鏈,區塊鏈也不是比特幣。區塊鏈在未來可以有哪些應用呢?
實際上,區塊鏈解決的核心問題是信任問題。所有的金融機構,銀行、保險、券商等等,讓它們賴以生存的根本是信用,我們之所以會放心地買股票、買期貨、買紙黃金,都是因為我們信任充當交易中介的機構,而這些交易中介,就是金融活動的中心,我們寧願為此付出一定的手續費、交易費,金融機構也因此掙得盆滿缽滿。
但是,當區塊鏈在人們的觀念上和技術上都成熟後,這種中心化的金融機構是有可能被顛覆掉的,因為我們可以利用區塊鏈的理念和技術來改寫遊戲規則,讓所有的金融產品交易都不再需要一個中心,而全部以點對點的方式完成,並且從理論上能夠保證信用問題。
到了那時,銀行還需不需要我不知道,因為銀行還涉及更復雜的國家利益問題,但是,一定會有很多商業金融機構受到區塊鏈的沖擊。
再比如,公證也是一個典型的中心化的販賣信用的機構,區塊鏈完全可以改寫公證行業。關於區塊鏈的應用,後文還會有詳細闡述。
到此,我們對比特幣和區塊鏈建立起了總體概念,接下來,我要幫你剝掉下一層洋蔥皮,了解一下比特幣系統的基本原理。
比特幣基本原理
數字指紋和非對稱加密
去中心化的賬本還是很容易理解的,只要把所有的交易記錄都記在每一臺電腦的賬本上,然後就可以用計算機的強大計算能力,隨時隨地查出每個人的余額是多少。
但是大家不要忘了,在網絡上記賬與線下記賬不同。網絡上都是消息來消息去的,大家根本不見面。
如果你收到一條信息,上面寫著「A支付5元錢給B」。這時,你不禁要問:
第一,如何確保這條信息內容的完整性?第二,如何確保信息的真實性?這兩個問題不解決,去中心化賬本的理想就無法實現。解決辦法是有的。我們先來看怎麽解決第一個問題:確保記賬信息的完整性。
這里要引入一個概念,就是數字指紋(很多文章中也叫數字簽名、哈希值)。電腦上的任何信息,按照國際統一的編碼標準,最終都是以0和1來存儲,這就是大名鼎鼎的二進製。例如「錢」這個字用二進製表示就是「1001010010110001」,再比如「A支付5元錢給B」這句話,用二進製表示就是:
0100000111001010010111110011101101100000110101101000101000011100101001011000111111101101100101000010
普通人看到二進製往往無法和數字建立聯系,實際上,這串二進製數字也可以用一組十進製的數字來表示,它們完全相等:
100000111001010080606408664086260086008422488464406842602666664446622202242228042826680682422068400
看到了十進製的數,很多人才會認為這確實是一個「數字」。這就是數字指紋了嗎?還不是。
二進製和原始信息只是一一對應的編碼關系,一個英文字母或者數字對應8個比特,一個中文字符對應16比特,原始信息越長,二進製編碼也越長。任何原始信息都可以轉換成一串數字,有了數字就可以做數學運算,玩出各種花樣了。
現在,我們給數學家提出一個要求:請設計一個算法,將任何一條信息,不論長短,都計算出一個唯一的「數字指紋」與它對應。但有兩個附加條件:一、指紋的長度必須固定;二、只能從「原始信息」計算出「指紋」,誰也無法從「指紋」反向計算出「原始信息」。
這個要求,看似很過分,但是難不倒數學家。1993年,美國國家安全局發布了SHA算法,全稱是Secure Hash Algorithm,中文一般翻譯為「安全散列算法」或者「安全哈希算法」,這個名稱估計把你嚇到了,聽著特學術(我有時候會聽人說「嘻哈算法」,忍不住偷笑一下,各位千萬別讀錯)。
Hash這個詞沒有對應的中文意譯詞,如果讓我來意譯的話,我會翻譯為「數字摘要算法」,基本上能表達該算法的含義,就是從目標對象中提取出一個特征摘要,好像人的指紋一樣。
SHA算法從1993年發布它的第零代,一直到2015年發布第三代,二十二年間已經升級了四次。比特幣用到的是第二代算法,簡稱為SHA-256算法,這里的「256」表示,由這個算法生成的指紋長度固定為256比特。大家可以很容易在網上找到在線生成SHA-256指紋的網頁,這個算法是公開的,誰都能用,例如,「錢」字的SHA-256指紋是:
0000111010111000011000111100011110001101101000111110001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
「A支付5元錢給B」的SHA-256指紋是:
1111011110111011001010011011101011011111000001011101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
大家看到,不論原始信息有多長,生成的指紋都是一樣長的。而且這個指紋還有兩個顯著特點:一、原始信息只要改變一點點,哪怕只改動一個數字,整個指紋就會發生巨大的變化,毫無規律可循;二、截至本文寫作時,世界上還沒有任何公開的方法可以從指紋反向計算出原始信息,普遍認為理論上無法破解。
不過,在實際的使用中,256位的二進製數據太長了,使用起來極不方便,還很容易看花眼。於是,指紋通常用十六進製來顯示,反正二進製到十六進製是一一對應的。
「錢」的十六進製指紋是:
0eb863c78da3e38b6b92d1f3999566e5d8e17a6f700a112c8993cf6bfc48f70b
「A支付5元錢給B」的十六進製指紋是:
f7bb29badf05d41e60b1036d749f134a901c7a97daef7a1fe4e1e14471bd4833
這樣看起來就簡潔多了,我們可以試一下把「5元錢」改為「6元錢」,看看指紋的變化有多大,下面是改後的指紋:
1d48da12b0fb29efe6f690185922f96d259bd887343735898bfc3901a83b58c3
看到了吧,僅僅改動了一個數字,但指紋幾乎沒有一位是相同的。這就是SHA算法的神奇之處,也確保了指紋沒有規律可循,無法被反向破譯。
有了數字指紋,就可以解決第一個問題:確保記賬信息的完整性。怎麽做?很簡單,我們只要做出一個規定,任何發出信息的一方,必須同時發出原始信息的指紋。那麽收到信息的一方只需要用公開的SHA-256算法把原始信息也生成一個指紋,和收到的指紋比對一下,如果一致,就說明收到的信息是完整的;如果不一致,說明收到的原始信息由於某種原因被修改過了,這個原因可能是數據傳輸過程中的錯誤,也可能是被人篡改了等等。
那會不會有一種巧合,原始信息和指紋都因為某些傳輸錯誤發生了改變,恰好錯誤的指紋數據就是出錯後的原始信息指紋,也就是負負得正了?這事當然不是絕對的不可能,但是從概率上來說,想要自然發生,大概等到宇宙滅亡了也不會發生一次,概率已經低到可以徹底忽略。
不過,你可能也想到了,還有一種可能性,就是黑客惡意篡改。因為SHA算法是公開的,如果有一個黑客攔截了原始信息和指紋,他把原始信息修改掉,比如把「A支付5元錢給B」改為「A支付5元錢給C」,同時生成新的指紋發送給你。這該怎麽辦呢?這就是我們要解決的第二個問題:如何確保信息的真實性?解決這個問題,等於也解決了信息發送方想抵賴的問題。
解決第二個問題的關鍵就是給指紋加密,但是,這種加密還不能是我們在諜戰劇里看到的那種電報加密的方式。大家不妨回憶一下看過的諜戰劇,我地下工作者收到一封電報,上面寫著2352,於是他從書架上拿出一本書,翻到第23頁,再數到第52個字,寫著一個「撤」字。這就是組織上通知這位同誌馬上撤退,有人叛變了。這種加密方式的壞處在於,只要敵人也掌握了密碼本,不但可以破譯電報,還能發送假電報釣魚,原因就在於加密和解密的方法是完全一樣的,能解密就能加密,所以,這種加密方法被叫作「對稱加密」,解密的過程只不過是加密的逆過程而已。
「對稱加密」用在我們想要的去中心化賬本系統中就不好使了,因為我們既要讓網絡上的每一個信息接收者能夠解開密文知道原始信息,又要讓黑客即使拿到密文也只能幹瞪眼,無法篡改密文。
個中關鍵,在於加密和解密的方法必須不一樣。所以,就要求數學家搞出一種全新的加密算法,這種算法是非對稱的,加密、解密不是互逆的過程。
能不能搞出這樣一個巧妙的加密算法呢?當然是能的,否則就不會有比特幣了嘛。下面我用一個簡化版的非對稱加密算法模擬一下我們想實現的效果。
原始信息是一組數字:269。
現在,我用一種只有我自己才知道的加密算法得到一個密文:24479。
然後,我把24479告訴所有人的同時,還宣布:解開我這條密文的鑰匙就是數字11(後面我們就把這個公開的鑰匙稱為公鑰),任何人只要用24479乘以11,取結果的後三位,就能得到我想要告訴大家的原始信息。不信嗎?我們試試看:
24479×11=269269
哇,好有意思,不單後三位,連前三位都是原始信息。我是怎麽加密的呢?很簡單,我把原始信息乘以91就是密文,而這個91就可以叫「私鑰」,我私人的加密鑰匙。這樣就實現了加密和解密是完全不一樣的兩種算法。
你可以試試看,用任意一個三位數字乘以91,得到的結果再乘以11,最終得到的結果一定是原始三位數寫兩遍。例如:218×91×11=218218。
如果用任意一個二位數字乘以91,得到的結果再乘以11,最終得到的結果後二位數字也一定與原始數字相同。例如:18×91×11=18018,至於它背後的數學原理,稍微琢磨一下就能想明白了。
但是請記住,我舉的這個例子只是讓你體會一下什麽叫非對稱加密,因為這個例子的算法太過簡單,所以知道了公鑰是11的人,很容易猜出私鑰是91。但是比特幣系統采用的算法比這個復雜多了,那個算法確保了任何人即使知道原文、密文、公鑰,也無法猜到私鑰。也就是說,黑客只能解密,但不會加密,無法修改密文。
這麽牛的算法,就是聲名遠播的「橢圓曲線算法」,簡稱為ECC算法。
它是在1985年由兩位美國人尼爾·庫伯利茲(Neal Koblitz)和維克托·米勒(Victor Miller)分別獨立提出的。在密碼學中的廣泛使用,也就是最近十多年的時間,數學家真的很厲害。有了這個算法,就能確保去中心化的記賬系統中,每條交易記錄的真實性。我們來演示一下比特幣的去中心化記賬系統如何利用SHA和ECC算法確保賬本的完整性和真實性(以下是簡化後的原理說明,真實過程還要復雜很多,但原理不變)。
需要記賬的原始交易信息:A支付5元錢給B(以下簡稱「原文」)。
第一步:利用SHA將原文生成數字指紋:
f7bb29badf05d41e60b1036d749f134a901c7a97daef7a1fe4e1e14471bd4833
第二步:隨機生成一個私鑰,它的格式與指紋是完全一樣的,例如:
18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
第三步:利用ECC將第一步得到的數字指紋通過私鑰加密,得到密文:
869ac57b83ccf75ca9da8895823562fffb611e3c297d9c2d4612aeeb32850078
第四步:根據私鑰生成一個公鑰:
600FFE422B4E00731A59557A5CCA46CC183944191006324A447BDB2D98D4B408
第五步:將原文、密文和公鑰廣播到整個比特幣網絡中。信息發送步驟到此結束,以下是信息接收步驟。
第六步:接收方利用ECC將密文通過公鑰解密,得到指紋1。
第七步:利用SHA將原文生成數字指紋,得到指紋2。
第八步:比對指紋1是否等於指紋2。
第九步:如果相等,則確認該條信息是合法交易信息,添加到自己的賬本中。如果不相等,則拋棄該信息。至此全部結束。在真實的比特幣網絡中,交易雙方都是完全匿名的,交易者A或者B都是賬號(有些文章中稱「地址」,含義一樣),賬號背後的主人信息是沒有任何記錄的,可以是一條狗,也可以是一個人工智能,而賬號則是根據公鑰,通過一定的算法生成的。
一個私鑰幾乎可以生成無數個不同的對應公鑰,也就意味著可以生成幾乎無數個不同的對應賬號。誰掌握了私鑰,誰就是賬號的主人。
比特幣網絡中,私鑰是動用賬號中比特幣的唯一憑證,如果你的私鑰被盜,你就永遠失去了它,打官司也要不回來,因為沒有任何方式可以證明他的私鑰是從你這里偷走的。