大家剛開始使用錢包的時候都會被助記詞、Keystore、私鑰、地址、公鑰等各種概念搞得云里霧里,這些概念和傳統世界的銀行卡和密碼簡單的兩個概念完全不一樣,只能按照錢包軟件的提示需要怎么做就怎么做,卻無法知道緣由,有點兒死背書的感覺,本篇的主旨就是幫大家捋一捋:作為一款區塊鏈錢包,是如何工作的,如何生成密鑰、助記詞、Keystore等。先把結論置頂:
區塊鏈錢包實現的技術原理用一句話表示就是:錢包助記詞生成了種子(Seed),種子(Seed)生成了私鑰,私鑰推導出公鑰,公鑰節選部分成了錢包地址。同時錢包提供了keystore,它也是私鑰加密后的文件,可以配合正常的密碼使用,便捷了用戶的錢包使用。
區塊鏈的誕生,不僅僅是通過代碼和智能合約來將生產組織進一步扁平化,從而達到優化中間過程、精簡中介的作用,更是產生了一個新的經濟模式,創建了一種新的生產關系,這種理念上的變革遠遠大于技術本身帶來的影響,它最讓人著迷的地方莫過于利用人性的特點,建立的一套自治的經濟激勵機制,并誕生了一個新型的價值載體cryptocurrency(筆者習慣區分Coin和Token,可參見文章區塊鏈基礎概念 - 理解COIN和TOKEN)。
Cryptocurrency顯然不同于傳統的貨幣,它是通過一定的加密算法計算出來的數字貨幣,也就是說電子化會是它的本質屬性,這樣它的存儲問題就會是一個熱門的研究領域,具體來講就是我們常說的區塊鏈錢包。當然,這里需要強調的是,區塊鏈錢包并不是存儲著大家的cryptocurrency,它是在鏈上存儲的,錢包主要存儲的是私鑰,它是用戶對鏈上cryptocurrency的所有權憑證,這是一個不記名、不可掛失的憑證。從開發者的角度看,錢包的作用就是管理用戶的私鑰、通過私鑰簽名交易管理用戶在區塊鏈上的數字貨幣Cryptocurrency Address + Private key = Cryptocurrency Wallet。
以上屬于對錢包相對傳統的一個定義,筆者最近結識到AlphaWallet的聯合創始人&CEO Victor Zhang對錢包的理解非常的獨樹一幟和有見解:區塊鏈錢包,其實更好叫做區塊鏈客戶端,其中“錢”只是其中一個應用場景。當然他們這個團隊主要focus在帶有智能合約的公鏈錢包,目前主要就是ETH了,以其作為基礎衍生出眾多應用場景供使用,而不是傳統理解的錢包概念了。筆者以前一直覺得在未解決Cryptocurrency價值波動前,錢包的用戶大規模朝潮還很久遠,不能與交易所抗衡,但終究有一天王位會轉移給錢包。在聽了Victor的見解之后,筆者突然覺得視野更加開闊。BTW,他們團隊還是ERC875的執筆,對技術的追求和開發很有造詣,是個值得關注的團隊!
【區塊鏈錢包基本類型和特點】
區塊鏈錢包的分類和描述依照所涉及的概念不同會有所區別,從其本質特點上來講,可用下圖來表示:
區塊鏈錢包本質特點劃分
區塊鏈錢包和區塊鏈一樣,也可以分為去onchain錢包和offchain錢包(如今很多人習慣稱之為中心化錢包和去中心化錢包,雖然方便無基礎的人形象理解,但是整個概念和精髓卻會被誤解),它們本質區別在于錢包私鑰的存儲方式和地點,私鑰存儲在用戶手中,錢包商無獲取途徑,用戶可以實時使用鏈上資產的稱之為onchain錢包;而私鑰存儲在錢包商或者交易所手中,用戶不能直接使用鏈上資產而需要通過第三方才能動的稱之為offchain錢包。具體來講:
1.onchain錢包——全節點錢包
私鑰存儲在用戶手中,同時全節點錢包還保存了所有區塊的數據,這樣就可以在本地直接驗證交易數據的有效性。大部分全節點錢包也具備挖礦功能,它自身也是區塊鏈網絡中的一個節點,如BTC的Bitcoin Core;ETH的Mist,Parity等。
優點:
一般屬于官方為區塊鏈設計的錢包,直接onchain,不需要經過第三方發起交易,保證了基本安全性;
缺點:
也因為下載了所有節點,所以占用很多硬盤空間(Mist現在達到了80G,筆者下了好幾天也失敗了;Bitcoin Core據說是150G);
每次使用前需要同步數據;
新手的使用體驗不夠好;
不支持多種數字資產;
往往都是電腦版本。
2.onchain錢包——SPV輕錢包
私鑰存儲在用戶手中,但不保存所有區塊的數據,只保存跟自己相關的數據,所以體積很小,可以運行在電腦,手機,網頁等地方。如Blockchain, imtoken等。
優點:
用戶體驗很好,尤其對于新手
很多輕錢包都支持多種數字資產
體積小,不占空間
缺點:
交易驗證會稍微慢一點
3.offchain錢包——通過中心服務器訪問區塊鏈網絡的錢包
該類型錢包的劃分有一定爭議,主要在于錢包數據傳輸的方式是可以擴展選擇區塊鏈節點還是必須通過錢包服務方的服務器,如果是后者就存在私鑰存儲在中心化服務器的風險,目前有很多區塊鏈錢包體驗都很不錯,甚至很流暢,由于不開源無法排除該類風險。筆者推斷比特購錢包應該屬于此類。
優點:
同SPV輕錢包
用戶體驗會比onchain錢包好
缺點:
存在安全風險(雖然真正致力做區塊鏈的錢包企業哪怕即使通過自己的服務器將交易信息發送到節點上,即不會作惡,但是不能排除可能有作惡的人可以使用這種方式獲得用戶密鑰)
會比onchain錢包交易驗證更慢,但是用戶可能體會不到。
4.offchain錢包——第三方托管錢包
完全依賴運行這個錢包的公司和服務器,存在某個組織或者個體的錢包地址里,中心化交易所里的Cryptocurrency就是在offchain錢包(交易所)里保存的。
優點:
私鑰忘記了可以找回
平臺會把私鑰安全做的不錯
一般以企業作為信用背書
缺點:
你的私鑰控制在平臺手上,平臺“做壞事”你是無法阻止的,即作惡風險
平臺關閉后你的幣就沒有了,即跑路風險
當然,根據不同的表現形式,我們還可以有不同的劃分:
這種劃分理解就比較簡單了,電腦單機版的錢包,如前面提到的全節點錢包基本以此類為主;手機錢包和在線錢包以SPV輕錢包為主,前者以手機APP為主要表現形式,后者是網頁插件,如MyEtherWallet, MetaMask等。硬件錢包是為了增強安全性,通過專門設計的安全硬件來離線保存儲私鑰,隔絕黑客入侵。
所以,電腦錢包、手機錢包、在線錢包一般體現的都是實時可用性,它們更多被稱之為熱錢包,即實時在線,這樣就存在被黑客攻擊的風險;于是硬件錢包作為常年離線保存,更多稱之為冷錢包,即離線保存。
但是硬件錢包往往需要購置單獨的硬件設備,所以在成本上會付出更多,同時使用的便利性也不如熱錢包,因為實時在線可用。當然也有使用優盤來自己制作硬件錢包的,一方面制作過程比較繁瑣,同時每次轉賬支出時會比較繁瑣,適用于比較有基礎的人士。
優點:
安全,私鑰不觸網,黑客無法通網絡攻擊。另外設備都有PIN碼保護,即使在物理環境中設備被盜走,也無法打開你的錢包;
易備份,設備在初始化配置的時候會生成助記詞(一般為12個或者24個單詞),而助記詞就是你私鑰的備份,當你的設備丟失或者損壞以后,可以夠買新的設備然后通過助記詞來恢復私鑰;
多幣種同時管理,現在絕大多數的硬件錢包,不僅僅可以管理比特幣,像萊特幣、以太坊、比特現金等數字貨幣都可以同時管理。
缺點:
不免費,你要為硬件付費;
無法獨立使用,硬件錢包都是隔絕網絡的,所以需要配合聯網的客戶端(Chrome 插件、桌面客戶端、手機客戶端等)來完成收幣和發幣。不過為了安全犧牲一些方便些也是值得的,畢竟一個比特幣8000刀,丟半個都疼。
【區塊鏈錢包實現技術原理】
理解區塊鏈錢包實現技術原理,先要理解:
1.私鑰、公鑰和地址產生的方法,這是區塊鏈的相關知識;
2.接著理解如何使用API進行遠程調用等基礎概念,這是傳統IT行業相關知識;
3.最后就是錢包設計相關的助記詞, keystore和密碼的概念,它和區塊鏈公鑰、私鑰和地址產生的方式思路一樣,但是整個過程屬于區塊鏈錢包設計過程,不能與區塊鏈的相關知識混淆。
一、私鑰、公鑰和地址產生的方式(以BTC為例):
1.比特幣私鑰其實是使用SHA-256生成的32字節(256位)的隨機數,有效私鑰的范圍則取決于比特幣使用的secp256k1 橢圓曲線數字簽名標準。
2.在私鑰的前面加上版本號,后面添加壓縮標志和附加校驗碼,(所謂附加校驗碼,就是對私鑰經過2次SHA-256運算,取兩次哈希結果的前四字節),然后再對其進行Base58編碼,就可以得到我們常見的WIF(Wallet import Format)格式的私鑰。
3.私鑰經過橢圓曲線乘法運算,可以得到公鑰。公鑰是橢圓曲線上的點,并具有x和y坐標。公鑰有兩種形式:壓縮的與非壓縮的。早期比特幣均使用非壓縮公鑰,現在大部分客戶端默認使用壓縮公鑰。
從私鑰推導出公鑰、再從公鑰推導出公鑰哈希都是單向的,也就是采用不可逆算法。
橢圓曲線算法
4.公鑰產生后,將公鑰通過SHA256哈希算法處理得到32字節的哈希值;后對得到的哈希值通過RIPEMD-160算法來得到20字節的哈希值 ——Hash160
5.把版本號[2]+Hash160組成的21字節數組進行雙次SHA256哈希運算,得到的哈希值的頭4個字節作為校驗和,放置21字節數組的末尾。
6.對組成25位數組進行Base58編碼,最后得到地址。
下圖以非壓縮格式的65字節公鑰示意上述過程:
二。遠程過程調用(RemoteProcedure Call, RPC)
它是一個計算機通信協議。該協議允許運行于一臺計算機的程序調用另一臺計算機的子程序,而程序員無需額外地為這個交互作用編程。RPC 的主要功能目標是讓構建分布式計算(應用)更容易,在提供強大的遠程調用能力時不損失本地調用的語義簡潔性。廣為使用的是一個叫做 JSON(JavaScript Object Notation)- RPC 的協議。所以錢包都是通過某個區塊鏈RPC接口調用來和區塊鏈網絡進行交互。
這里列出主流項目相關的 RPC 接口以及開源錢包項目,以供參考。
Bitcoin:
1.RPC
Original Bitcoin client/API calls list
API reference (JSON-RPC)
JSON RPC API
2.Wallet
Bitcoin Core,官方出品
bitcoinj,比特幣協議 Java 版
bither,簡單安全的比特幣錢包
Electrum,全平臺輕錢包
bread,iOS 錢包
Mycelium,Android 錢包
Copay,同時支持 Bitcoin 和BitcoinCash
bitcoin-wallet,又一款 Android 錢包
DotNetWallet,.NET 實現的錢包
Coinpunk,基于瀏覽器的錢包
btcwallet,Go 實現的錢包
Ethereum/ERC20
1.RPC
JSON RPC
JSON RPC API
Management APIs
ethjsonrpc
web3.py
2.Wallet
go-ethereum,以太坊協議 Go 版
Mist,官方出品
Parity,支持 Windows、Mac、PC 的錢包
MetaMask
MyEtherWallet,基于瀏覽器的錢包
eth-lightwallet,輕量級 JavasSript 版本錢包
ethaddress.org,紙質版錢包生成器
Neureal wallet,支持 Windows、Mac、PC 的錢包
其他
1.Zcash
Zcash,官方出品
2.BitShares
BitShares,官方出品
3.Sia
Sia,官方出品
4.Nem
NanoWallet,官方出品
5.Dash
Dash,官方出品
6.Qtum
Qtum Core Wallet,官方出品
7.Litecoin
Litecoin,官方出品
8.IOTA
IOTA Wallet,官方出品
9.Monero
Monero,官方出品
10.GXS
GXS Wallet for mobile,官方出品
11.EthereumClassic
Ethereum Classic Wallet,官方出品
三、錢包設計相關的助記詞(mnemonic),keystore和密碼的概念
私鑰一般太難記憶了,使用也不方便,所以從錢包設計的角度,就為簡化操作同時不丟失安全性,就出現了助記詞的方法。
一般情況下,助記詞由一些單詞組成,只要你記住這些單詞,按照順序在錢包中輸入,也能打開錢包。
根據密鑰之間是否有關聯可把錢包分為兩類:nondeterministic wallet 和 deterministic wallet。
nondeterministic wallet:密鑰對之間沒有關聯;
deterministic wallet: 密鑰對由一個原始的種子主密鑰推導而來。最常見的推導方式是樹狀層級推導 (hierarchical deterministic) 簡稱 HD。
比特幣錢包 (Bitcoin Core) 生成密鑰對之間沒有任何關聯,屬于 nondeterministic wallet ,這種類型的錢包如果想備份導入是比較麻煩的,用戶必須逐個操作錢包中的私鑰和對應地址。
deterministic wallet基于BIP32(Bitcoin Improvement Proposal 32) 標準實現,通過一個共同的種子維護n多私鑰,種子推導私鑰采用不可逆哈希算法,在需要備份錢包私鑰時,只備份這個種子即可。
通過9個步驟即可生成錢包助記詞和種子,其中步驟1~6生成助記詞,步驟7~9把前六步生成的助記詞轉化為BIP32 種子:
生成助記詞:
規定熵的位數必須是 32 的整數倍,所以熵的長度取值位128 到 256 之間取 32 的整數倍的值,分別為 128, 160, 192, 224, 256;
校驗和的長度為熵的長度/32 位, 所以校驗和長度可為 4,5,6,7,8 位;
助記詞庫有 2048 個詞,用 11 位可全部定位詞庫中所有的詞,作為詞的索引,故一個詞用 11 位表示,助記詞的個數可為 (熵+校驗和)/11,值為 12,15,18,21,24
助記詞規則
1.生成一個長度為 128~256 位(bits)的隨機序列(熵);
2.取熵哈希后的前n位作為校驗和(n= 熵長度/32);
3.隨機序列+校驗和;
4.把步驟3得到的結果每 11位切割;
5.步驟4得到的每11位字節匹配詞庫的一個詞;
6.步驟5得到的結果就是助記詞串;
錢包生成助記詞方法
通過助記詞生成種子
助記詞由長度為128 到 256 位的隨機序列(熵)匹配詞庫而來,隨后采用PBKDF2 function推導出更長的種子(seed)。生成的種子被用來生成構建 deterministic Wallet 和推導錢包密鑰。
在密碼學中,Key stretching技術被用來增強弱密鑰的安全性,增加了暴力破解 (Brute-force attack) 對每個可能密鑰嘗試攻破的時間,增強了攻擊難度。各種編程語言原生庫都提供了 key stretching 的實現。PBKDF2(Password-Based Key Derivation Function 2)是常用的 key stretching 算法中的一種。基本原理是通過一個為隨機函數(例如HMAC 函數),把明文和鹽值作為輸入參數,然后重復進行運算最終產生密鑰。
為了從助記詞中生成二進制種子,BIP39 采用 PBKDF2 函數推算種子,其參數如下:
7.助記詞句子作為密碼;
8.“mnemonic” + passphrase 作為鹽;
9.2048 作為重復計算的次數+HMAC-SHA512 作為隨機算法,最終得到BIP32 種子,512 位(64 字節)是期望得到的密鑰長度;
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
助記詞生成種子
主私鑰和主鏈碼:
首先是從根種子生成主密鑰 (master key) 和主鏈碼 (master chain code)
種子生成密鑰
上圖中根種子通過不可逆HMAC-SHA512算法推算出512位的哈希串,左256位是Master Private key(m),右256位是master chain code,通過m結合推導公鑰的橢圓曲線算法能推導出與之對應的264位master public Key (M)。chain code作為推導下級密鑰的熵。
同時錢包還提供了keystore和密碼基本功能
用戶最好的體驗仍然會是密碼方式,所以錢包還提供了keystore讓用戶導出保存,這個Keystore也是私鑰經過加密過后的一個文件,需要你自己設置的密碼才能打開文件。這樣的好處是就算keystore文件被盜,只要你額外設置的密碼夠長夠隨機,那么短時間內私鑰也不會泄露,有充足的時間轉移地址里面的加密貨幣到其他地址。Keystore會存儲在使用的設備里,這樣每次登陸只用輸入相應密碼即可。
【總結】
所以區塊鏈錢包實現的技術原理用一句話表示就是:錢包助記詞生成了種子(Seed),種子(Seed)生成了私鑰,私鑰推導出公鑰,公鑰節選部分成了錢包地址。同時錢包提供了keystore,他也是私鑰加密后的文件,可以配合正常的密碼使用,便捷了用戶的錢包使用。
所以,理解了一個錢包的生成原理之后就會更加理解下面幾種錢包丟失的情況:
1.地址忘了,可以用私鑰、助記詞、keystore+密碼,導入錢包找回。
2.密碼忘了,可以用私鑰、助記詞,導入錢包重置密碼。
3.密碼忘了,私鑰、助記詞又沒有備份,就無法重置密碼,就不能對代幣進行轉賬,等于失去了對錢包的控制權。
4.密碼忘了,keystore 就失去了作用。
5.私鑰忘了,只要你錢包沒有刪除,并且密碼沒忘,可以導出私鑰。
6.私鑰忘了,還可以用助記詞、keystore+密碼,導入錢包找回。
7.助記詞忘了,可以通過私鑰、keystore+密碼,導入錢包重新備份助記詞。
8.keystore忘了,只要你錢包沒有刪除,密碼沒忘,可以重新備份keystore。
9.keystore 忘了,可以通過私鑰、助記詞,導入錢包重新備份 keystore。
【私鑰重復疑惑】
最后問題來了,根據私鑰產生的機制就會有重復的可能。
私鑰有32個字節(1字節=8位二進制),所以私鑰的總數是2^(8*32)=2^256個≈10^77個。假設全宇宙都在窮舉私鑰:
假設宇宙有一億個星系,
每個星系有一億顆恒星,
每顆恒星有一億顆人造衛星,
每顆人造衛星上有一億臺超級計算機,
每臺超級計算機有一億個CPU,
每個CPU每秒可以窮舉一億個私鑰。
假設有一億個私鑰的地址上有BTC(每個地址平均0.21BTC),那么,多久可能窮舉出一個有幣的私鑰為:
10^77(私鑰總數)/10^8(有幣私鑰)/10^8(星系)/10^8(恒星)/10^8(衛星)/10^8(超級計算機)/10^8(CPU)/10^8(每秒窮舉)=10^21秒。
10^21秒/3600秒/24小時/365天=317098億年。
現在宇宙年齡為138.2億年,相對來說,假如全宇宙都在窮舉私鑰,每1000倍宇宙年齡,可以期望窮舉到0.21 BTC。
以上查詢得到的計算方式只是說明概率很小很小,小到可以忽略不計,但是隨著時間軸的累積,加上現在不僅僅是BTC,還有各種各樣的新公鏈,如果都使用同樣的私鑰生成地址的規則,有概率就意味著最終無線長時間總會出現重復的情況。而且概率學的范疇無法預測到偶然事件:如就偶然撞上了一次重復事件。
所以,筆者理解:只能說刻意去窮舉私鑰投機的方式是不具備性價比(完全不可取或者說代價慘重)的,在這樣的默認假設下,萬一出現偶然事件,生成錢包地址時會進行網絡驗證,如果發現重復(注意理論上即使地址重復也未必私鑰會重復,但是算法上通過限制私鑰生成的范圍來保證不會有兩個私鑰對應同一公鑰的情況,所以還是可以理解成私鑰和地址一一對應)就重新生成新的,并不會出現資產損失的可能。
評論