理解開發HD 錢包涉及的 BIP32、BIP44、BIP39

如果你還在被HD錢包、BIP32、BIP44、BIP39搞的一頭霧水,來看看這邊文章吧。

數字錢包概念

錢包用來存錢的,在區塊鏈中,我們的數字資產都會對應到一個賬戶地址上, 只有擁有賬戶的鑰匙(私鑰)纔可以對資產進行消費(用私鑰對消費交易簽名)。
私鑰和地址的關係如下:理解開發HD 錢包涉及的 BIP32、BIP44、BIP39
(圖來自精通比特幣)
一句話概括下就是:私鑰通過橢圓曲線生成公鑰, 公鑰通過哈希函數生成地址,這兩個過程都是單向的。
因此實際上,數字錢包實際是一個管理私鑰(生成、存儲、簽名)的工具,注意錢包並不保存資產,資產是在鏈上的。

如何創建賬號

創建賬號關鍵是生成一個私鑰, 私鑰是一個32個字節的數, 生成一個私鑰在本質上在1到2^256之間選一個數字
因此生成密鑰的第一步也是最重要的一步,是要找到足夠安全的熵源,即隨機性來源,只要選取的結果是不可預測或不可重複的,那麼選取數字的具體方法並不重要。
比如可以擲硬幣256次,用紙和筆記錄正反面並轉換爲0和1,隨機得到的256位二進制數字可作爲錢包的私鑰。
從編程的角度來看,一般是通過在一個密碼學安全的隨機源(不建議大家自己去寫一個隨機數)中取出一長串隨機字節,對其使用SHA256哈希算法進行運算,這樣就可以方便地產生一個256位的數字。

實際過程需要比較下是否小於n-1(n = 1.158 * 10^77, 略小於2^256),我們就有了一個合適的私鑰。否則,我們就用另一個隨機數再重複一次。這樣得到的私鑰就可以根據上面的方法進一步生成公鑰及地址。

BIP32

錢包也是一個私鑰的容器,按照上面的方法,我們可以生成一堆私鑰(一個人也有很多賬號的需求,可以更好保護隱私),而每個私鑰都需要備份就特別麻煩的。
最早期的比特幣錢包就是就是這樣,還有一個暱稱:“Just a Bunch Of Keys(一堆私鑰)“

爲了解決這種麻煩,就有了BIP32 提議: 根據一個隨機數種子通過分層確定性推導的方式得到n個私鑰,這樣保存的時候,只需要保存一個種子就可以,私鑰可以推導出來,如圖:
理解開發HD 錢包涉及的 BIP32、BIP44、BIP39
(圖來自精通比特幣)上圖中的孫祕鑰就可以用來簽發交易。

補充說明下 BIP: Bitcoin Improvement Proposals 比特幣改進建議, bip32是第32個改進建議。
BIP32提案的名字是:Hierarchical Deterministic Wallets, 就是我們所說的HD錢包。
來分析下這個分層推導的過程,第一步推導主祕鑰的過程:
理解開發HD 錢包涉及的 BIP32、BIP44、BIP39
根種子輸入到HMAC-SHA512算法中就可以得到一個可用來創造主私鑰(m) 和 一個主鏈編碼( a master chain code)這一步生成的祕鑰(由私鑰或公鑰)及主鏈編碼再加上一個索引號,將作爲HMAC-SHA512算法的輸入繼續衍生出下一層的私鑰及鏈編碼,如下圖:理解開發HD 錢包涉及的 BIP32、BIP44、BIP39
衍生推導的方案其實有兩個:一個用父私鑰推導(稱爲強化衍生方程),一個用父公鑰推導。同時爲了區分這兩種不同的衍生,在索引號也進行了區分,索引號小於2^31用於常規衍生,而2^31到2^32-1之間用於強化衍生,爲了方便表示索引號i',表示2^31+i。
因此增加索引(水平擴展)及 通過子祕鑰向下一層(深度擴展)可以無限生成私鑰。
注意, 這個推導過程是確定(相同的輸入,總是有相同的輸出)也是單向的,子密鑰不能推導出同層級的兄弟密鑰,也不能推出父密鑰。如果沒有子鏈碼也不能推導出孫密鑰。現在我們已經對分層推導有了認識。
一句話概括下BIP32就是:爲了避免管理一堆私鑰的麻煩提出的分層推導方案。

祕鑰路徑及BIP44

通過這種分層(樹狀結構)推導出來的祕鑰,通常用路徑來表示,每個級別之間用斜槓 / 來表示,由主私鑰衍生出的私鑰起始以“m”打頭。因此,第一個母密鑰生成的子私鑰是m/0。第一個公共鑰匙是M/0。第一個子密鑰的子密鑰就是m/0/1,以此類推。
BIP44則是爲這個路徑約定了一個規範的含義(也擴展了對多幣種的支持),BIP0044指定了包含5個預定義樹狀層級的結構:
<br/>m / purpose' / coin' / account' / change / address_index<br/>
m是固定的, Purpose也是固定的,值爲44(或者 0x8000002C)
Coin type
這個代表的是幣種,0代表比特幣,1代表比特幣測試鏈,60代表以太坊
完整的幣種列表地址:https://github.com/satoshilabs/slips/blob/master/slip-0044.md
Account
代表這個幣的賬戶索引,從0開始
Change
常量0用於外部鏈,常量1用於內部鏈(也稱爲更改地址)。外部鏈用於在錢包外可見的地址(例如,用於接收付款)。內部鏈用於在錢包外部不可見的地址,用於返回交易變更。 (所以一般使用0)
address_index
這就是地址索引,從0開始,代表生成第幾個地址,官方建議,每個account下的address_index不要超過20
根據 EIP85提議的討論以太坊錢包也遵循BIP44標準,確定路徑是m/44'/60'/a'/0/n
a 表示帳號,n 是第 n 生成的地址,60 是在 SLIP44 提案中確定的以太坊的編碼。所以我們要開發以太坊錢包同樣需要對比特幣的錢包提案BIP32、BIP39有所瞭解。
一句話概括下BIP44就是:給BIP32的分層路徑定義規範

BIP39

BIP32 提案可以讓我們保存一個隨機數種子(通常16進制數表示),而不是一堆祕鑰,確實方便一些,不過用戶使用起來(比如冷備份)也比較繁瑣,這就出現了BIP39,它是使用助記詞的方式,生成種子的,這樣用戶只需要記住12(或24)個單詞,單詞序列通過 PBKDF2 與 HMAC-SHA512 函數創建出隨機種子作爲 BIP32 的種子。
可以簡單的做一個對比,下面那一種備份起來更友好:

// 隨機數種子
090ABCB3A6e1400e9345bC60c78a8BE7  
// 助記詞種子
candy maple cake sugar pudding cream honey rich smooth crumble sweet treat

使用助記詞作爲種子其實包含2個部分:助記詞生成及助記詞推導出隨機種子,下面分析下這個過程。

生成助記詞

助記詞生成的過程是這樣的:先生成一個128位隨機數,再加上對隨機數做的校驗4位,得到132位的一個數,然後按每11位做切分,這樣就有了12個二進制數,然後用每個數去查BIP39定義的單詞表,這樣就得到12個助記詞,這個過程圖示如下:
理解開發HD 錢包涉及的 BIP32、BIP44、BIP39
(圖來源於網絡)

助記詞推導出種子

這個過程使用密鑰拉伸(Key stretching)函數,被用來增強弱密鑰的安全性,PBKDF2是常用的密鑰拉伸算法中的一種。
PBKDF2基本原理是通過一個爲隨機函數(例如 HMAC 函數),把助記詞明文和鹽值作爲輸入參數,然後重複進行運算最終產生生成一個更長的(512 位)密鑰種子。這個種子再構建一個確定性錢包並派生出它的密鑰。
密鑰拉伸函數需要兩個參數:助記詞和鹽。鹽可以提高暴力破解的難度。 鹽由常量字符串 "mnemonic" 及一個可選的密碼組成,注意使用不同密碼,則拉伸函數在使用同一個助記詞的情況下會產生一個不同的種子,這個過程圖示圖下:
理解開發HD 錢包涉及的 BIP32、BIP44、BIP39
(圖來源於網絡)
校驗和地址是EIP-55中定義的對大小寫有要求的一種地址形式。

密碼可以作爲一個額外的安全因子來保護種子,即使助記詞的備份被竊取,也可以保證錢包的安全(也要求密碼擁有足夠的複雜度和長度),不過另外一方面,如果我們忘記密碼,那麼將無法恢復我們的數字資產。

一句話概括下BIP39就是:通過定義助記詞讓種子的備份更友好

我爲大家錄製了一個視頻:以太坊去中心化網頁錢包開發,從如何創建賬號開始,深入探索BIP32、BIP44、BIP39等提案,以及如何存儲私鑰、發送離線簽名交易和Token。

小結

HD錢包(Hierarchical Deterministic Wallets)是在BIP32中提出的爲了避免管理一堆私鑰的麻煩提出的分層推導方案。
而BIP44是給BIP32的分層增強了路徑定義規範,同時增加了對多幣種的支持。
BIP39則通過定義助記詞讓種子的備份更友好。

目前我們的市面上單到的以太幣、比特幣錢包基本都遵循這些標準。

最後推薦一個助記詞祕鑰生成器網站

歡迎來知識星球提問,星球內已經聚集了300多位區塊鏈技術愛好者。
深入淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術博客。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章