大家剛開始使用錢包的時候都會被助記詞、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位元組的雜湊值 ——Hash260
5.把版本號[2]+Hash260組成的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,還有各種各樣的新公鏈,如果都使用同樣的私鑰生成地址的規則,有概率就意味著最終無線長時間總會出現重複的情況。而且概率學的範疇無法預測到偶然事件:如就偶然撞上了一次重複事件。所以,筆者理解:只能說刻意去窮舉私鑰投機的方式是不具備價效比(完全不可取或者說代價慘重)的,在這樣的預設假設下,萬一出現偶然事件,生成錢包地址時會進行網路驗證,如果發現重複(注意理論上即使地址重複也未必私鑰會重複,但是演算法上透過限制私鑰生成的範圍來保證不會有兩個私鑰對應同一公鑰的情況,所以還是可以理解成私鑰和地址一一對應)就重新生成新的,並不會出現資產損失的可能。
【參考文獻】
http://www.infoq.com/cn/articles/bitcoin-and-block-chain-part03
https://www.jianshu.com/p/41163f213e15
https://blockchain.info/zh-cn/api/blockchain_wallet_api
https://www.jianshu.com/p/e6a4150eb729
PBKDF2 演算法概述
分層確定性錢包 HD Wallet 介紹
Bitcoin developer-guide#wallets
Working with Bitcoin HD wallets II: Deriving public keys
List of address prefixes
https://www.jianshu.com/p/8191295e8b19
https://www.zhihu.com/question/27253380/answer/363379249
https://ethfans.org/posts/hardware-wallet-Ledger
http://8btc.com/article-2002-1.html
http://orchome.com/944
https://www.cnblogs.com/yitim/p/8880977.html
簡書地址:https://www.jianshu.com/u/0b4c8940c6c5
歡迎ERC20系列幣打賞:0xe7F9D2D4B6D3d8535Da330041aE7Ce814C35622B