4.2 熱儲存與冷儲存

如我們所看到的,把比特幣放在你的個人電腦裡就像把錢放在錢包裡帶著,這叫「熱儲存」。這很方便但很不安全。而另一方面,「冷儲存」是離線的,把比特幣鎖在其他地方。冷儲存不聯入互聯網,是封存起來的。所以相對安全和保險,但是很顯然不方便。這就像你帶著一些零錢出去,但是把終生積蓄鎖在保險箱裡的道理一樣。

要分開熱儲存和冷儲存,你也必須要用不同的私鑰,否則如果熱儲存被人破壞了,冷儲存也會處於危險之中。你也需要把幣在兩邊轉來轉去,這樣兩邊都需要知道對方的地址或公鑰。

因為冷儲存是離線的,所以熱儲存與冷儲存無法通過網絡相連,但其實冷儲存不需要上線就可以接收比特幣——熱儲存端知道冷儲存的地址,所以它隨時可以給冷儲存轉賬。當你覺得你的錢包裡的錢太多的時候,你可以把一部分的幣轉到冷儲存,但不需要讓冷儲存上線而暴露自己。當然,只要冷儲存上線,就可以接收到區塊鏈的轉賬信息,然後可以隨意處理這些比特幣。

但管理冷儲存有一個小問題:一方面,為了私密性和其他考慮,我們希望使用不同的地址(這些地址有不同的密鑰)收款。所以我們把比特幣從熱儲存轉到冷儲存的時候,要用一個新的冷儲存地址。但是由於冷儲存不上線,所以熱存儲端必須要能找到這樣的地址。

一個直接的解決方案是讓冷儲存一次性生成一批地址,然後把地址列表發送給熱儲存,熱儲存可以依次使用這些地址,當然,這個方法的缺陷是為了傳送地址,我們不得不經常讓冷儲存端上線。

分層確定性錢包

一個比較有效的解決辦法是使用一個分層確定性錢包(hierarchical deterministic wallet)。這個方法可以讓冷儲存端製造無限制的地址數量,然後通過一個短暫的、一次性的交換,讓熱儲存端知曉所有地址。但這需要使用密碼學的技巧。

回想一下,我們在第1章談到密鑰生成和電子簽名時,我們使用了「generateKeys」來生成一個公鑰(也就是地址)和一個私鑰。在分層確定性錢包裡,生成密鑰的方式不太一樣。不同於生成一個單一地址,我們生成一個被稱為「地址生成信息」的東西;我們也不只生成私鑰,而是生成「私鑰生成信息」。有了地址生成信息,我們就可以生成一系列地址。我們把地址生成信息和一個整數i作為地址生成函數的輸入參數,就生成了序列裡的第i個地址。同樣,我們用私鑰生成信息來生成一系列私鑰。

密碼學的神奇之處在於:對於每個i而言,第i個地址和第i個私鑰相匹配——換言之,第i個私鑰控制第i個地址的比特幣,就好像這是用經典辦法產生的。這樣一來,我們就有一長串配對的公鑰和密鑰。

密碼學的另一個技術優點是安全性——地址生成信息並不會洩露關於私鑰本身的任何信息。這意味著你可以放心地把地址生成信息給任何人,他就可以用它來生成第i個密鑰。

並不是所有的電子簽名算法目前都可用於生成分層確定性密鑰。比特幣使用的電子簽名算法ECDSA支持分層密鑰,讓我們可以使用這個技巧。即冷儲存端生成任意多個密鑰,熱儲存端生成相應的地址,見圖4.2。

圖4.2 分層確定性錢包示意

註:冷儲存端生成和保存私鑰生成信息和地址生成信息,然後將地址生成信息一次性轉給熱儲存端。當熱儲存端要給冷儲存端轉賬時,就按次序生成新的地址。冷儲存端上線後,也會按順序生成地址,然後查收相應地址收到的款項,直到某一地址沒有收款位置。如果冷儲存端需要向熱儲存端轉賬,它就會按順序生成私鑰序列。

ECDSA的工作機制如下:通常一個ECDSA私鑰是一個隨機數x,其對應的公鑰是gx。為了生成分層確定性密鑰,我們需要另外兩個隨機數k和y。

私鑰生成信息:k,x,y

第i個私鑰:x=y+H(k∥i)

地址生成信息:k,gy

第i個公鑰:gxi=gH(k∥i)·gy

第i個地址:H(gxi)

分層確定性錢包有我們需要的所有特性:兩方都可以生成公鑰/私鑰序列,而且這些公鑰/私鑰相互配對(因為與私鑰x對應的公鑰就是gx)。而且,這種方法還具有另外一種我們尚未提及的特性:當你向外提供這些公鑰時,這些公鑰之間沒有聯繫,也就是說,別人無法斷定這些公鑰來自同一個錢包。稻草人方案(冷儲存端生成大量的地址)也具有這種特性,但我們需要小心地保護這些地址,因為這些地址事實上並不是獨立生成的。這種特性對於保護隱私和實現匿名是至關重要的,我們將在第6章展開討論。

分層確定性錢包有兩種不同的安全性,熱儲存端的安全性較低。如果熱儲存受到損害,那麼上文提到的非相關性就不復存在,但這種情況下,私鑰(以及比特幣)仍然是安全的。通常,分層確定性錢包支持任意多個安全等級——這也是「分層」的由來——雖然,我們還沒有討論細節。這種安排非常有用,例如,當一家公司內部存在多種授權級別時,就需要這種特性。

現在,我們討論一下冷儲存如何保存信息(私鑰或私鑰生成信息)。第一種方式是將信息保存在某個設備(例如筆記本電腦、手機或平板電腦,或U盤)中,然後將這個設備好好保管,最好是讓這些設備斷開網絡,並將其鎖起來,這樣,如果有人想盜取信息,那麼他首先需要進入這些設備的保存處。

大腦錢包

第二種方法我們稱之為大腦錢包(brain walle)。這種方式下,你通過一個密碼就可以支取比特幣。大腦錢包無須使用硬件、紙張或者其他長期儲存介質。大腦錢包在物理安全性較差的情況下(例如跨國出差、旅行時)非常有用。

大腦錢包的主要原理是用一個可預測的算法把一個口令變成一對公鑰/私鑰。例如,你可以選擇一個哈希算法將口令轉譯成一個私鑰。在給定私鑰的情況下,可以用同樣的方法得到私鑰。進一步地,結合前文所提到的分層確定性錢包技術,你可以根據口令生成一整套地址和私鑰,從而實現錢包的完整功能。

但是,如果一個黑客猜到你的口令的話,他還是可以偷走你大腦錢包裡的所有私鑰。在電腦安全領域裡,我們通常假定黑客知道你生成密鑰的步驟,黑客不知道的只是你的口令。所以黑客可以嘗試使用不同的口令,生成地址,並在區塊鏈中查看這些地址上是否還存在未被使用的比特幣,一旦發現比特幣,黑客就可以迅速把這些比特幣轉給自己。黑客可能永遠都不知道(或者根本不關心)這些比特幣屬於誰,這類攻擊也不需要入侵任何設備,猜口令不針對任何人,所以也不會留下任何痕跡。

這種方法與嘗試破解電子郵箱密碼的方法不同,郵件服務器通常對密碼試錯有一定的次數或頻率限制(被稱為在線猜測),但是對於大腦錢包而言,黑客可以下載一堆未被使用的比特幣的地址,然後用電腦程序去慢慢地試錯,黑客都不需要知道大腦錢包的地址,這被稱為離線猜測或者密碼破解。相應地,設置口令的難度大大增加了,又要容易記,又要不容易被猜中。一種安全的方法是使用自動程序生成一個80位的數字,然後將其轉換成口令。

生成一個可記憶的口令

有一種簡便的方法可以生成口令:從最常用的10 000英語詞彙中,隨機選擇6個詞,從而生成大致80位長度的字節[6×log2(10 000)大致等於80]。很多人發現這個方法比隨機取字母容易記憶,因為這種方法生成的口令通常是下面這樣子的:

worn till alloy focusing okay reducing

earth dutch fake tired dot occasions

在實際操作中,我們可以讓程序生成密鑰的速度變慢(為程序加入一個延遲),這樣,黑客通過試錯法來破解私鑰就需要花費很長的時間,這就是所謂的密鑰延展(key stretching)。比如,為了使密鑰生成變慢,我們可以讓程序把本來很容易計算的哈希函數SHA-256算上220次,這樣一來就把黑客的工作量增加了220倍。當然,如果太慢的話,用戶在使用比特幣的時候,也會計算得很慢,這也很麻煩。

如果你徹底忘記了大腦錢包的口令,錢包裡的比特幣就永遠取不出來了。

紙錢包

第三個選擇是紙錢包(見圖4.3):把密鑰印在紙上,然後把紙鎖在保險箱裡。顯然,這種方式的安全程度取決於我們所使用的紙的安全程度。紙錢包通常用兩種方法為公私鑰匙編碼:二維碼和base58碼。就像大腦錢包一樣,只需要存儲少量關鍵信息,就可以重新建立一個紙錢包。

圖4.3 帶公鑰的比特幣紙錢包

註:同時使用了二維碼和base58碼加密。

防損硬件

第四種方法是使用防損硬件(tamper-resistant device),用它來保存密鑰或用它來生成密鑰,總之,此類設備本身不會洩露密鑰或輸出密鑰,而只是在我們按下設備的某個按鈕或輸入設備密碼後顯示密鑰的保管狀態。防損硬件的好處在於一旦設備丟失或者被盜,我們馬上就能知道。而且,想要盜走密鑰,必須先盜走這個設備。這和將密鑰保存在電腦上是不一樣的。

總而言之,用戶可使用上述一個或是多個方法來保存密鑰。對於熱儲存,尤其是存有大量比特幣的熱儲存而言,人們願意投入大量成本或先進的安全機制保護它們。我們將在下一章討論這些更先進的機制。

《區塊鏈:技術驅動金融》