BIP-39 規範主要描述了基於助記詞(一組便於記憶的單字)來生成確定性錢包的演算法和過程。
該規範中主要由兩部分構成:
如何生成助記詞;
如何將生成的助記詞轉化成一個二進位種子;
下面就先分別介紹這兩個部分來看看如何生成確定性錢包。
生成助記詞
生成助記詞的演算法過程如下圖:
具體過程如下:
建立一個 128 到 256 位(步長 32 位)的隨機序列(熵);
對上一步生成的隨機序列進行 SHA256 生成 Hash 值,並取出該 Hash 值的前 N 位(熵長/32,如:128 位,則 N = 4)作為隨機序列的校驗和(Checksum);
將 Checksum 添加至第一步生成的隨機序列的尾部,此時對於圖中示例加上 Checksum 之後為 128 + 4 = 132 位的隨機序列;
將上一步的隨機序列按照 11 位一段進行分隔(Split),這樣對於 128 位熵長的序列就會生成 12 段(132 / 11 = 12);
此時將每個包含 11 位部分的值與一個預定義的 2048 個單字的詞典進行對應;
按照切割順序生成了最終的單字組就是助記詞;
從助記詞生成種子
助記詞生成之後我們可以透過金鑰生成函數 PBKDF2 演算法來生成種子。
PBKDF2 需要提供兩個參數:助記詞和鹽(Salt)。其中 Salt 的目的是增加破解難度,而在 BIP-39 中,我們可以引入密碼(Passphrase)來作為保護種子的附加安全因素。
PBKDF2 is part of RSA Laboratories’ Public-Key Cryptography Standards (PKCS) series, specifically PKCS #5 v2.0, also published as Internet Engineering Task Force’s RFC 2898.
接著上面的助記詞生成之後,如下圖為生成 seed 的演算法過程:
PBKDF2 的第一個參數是上面生成的助記詞;
PBKDF2 的第二個參數就是 Salt,一般有字串和可選的使用者提供的密碼字串連接組成;
PBKDF2 使用 HMAC-SHA512 演算法,使用了 2048 次 Hash 之後產生一個 512 位的值作為種子;
從種子開始生成 HD 錢包
下面就將上面生成的種子作為 HD 錢包的根種子(Root Seed),任何 HD 錢包的根種子都可以重新創造整個 HD 錢包。
將 Root Seed 輸入到 HMAC-SHA512 演算法中可以得到一個 512 位的 Hash,該 Hash 的左邊 256 位作為 主私鑰 m(Master Private Key),右邊 256 位作為 主鏈碼(Master Chain Code)。之後的主公鑰 M(Master Public Key,264 bits)可以透過主私鑰 m 生成。
從上圖可以看到,HD 的金鑰生成如下幾個參數:
Parent Private Key 或 Parent Public Key;(均為未壓縮的 256 bits 的 ECDSA 密鑰
256 bits 的 Parent Chain Code;
32-bit 整型的 index number(索引號);
另外,上面的過程是可以遞迴下去的,圖中的 Child Private Key 可以作為其下一層級的 Parent Private Key。
透過將(Parent Publick Key, Parent Chain Code, Index Number)輸入至 HMAC-SHA512 演算法中,我們就可以生成其子金鑰,並且我們可以透過調整 Index Number 來生成同一層級的多個子金鑰。
關於擴展金鑰
因為這個金鑰衍生函數是單向的,所有 子金鑰 都是不能夠被用來推導出它們的 父金鑰 的,也不能推導出同層級的 姊妹金鑰 的,只有 父金鑰 和 父鏈碼(又是由 Parent 的 Parent 層級的 鑰匙 和 鏈碼 生成) 可以推導出所有的 子金鑰 和 子鏈碼,後續也就可以生成相應的 子公鑰 以及地址,並且用於對交易進行簽名。
將 金鑰 Key 和 Chain Code 結合起來稱為 擴展金鑰(Extended Key),可以透過 擴展金鑰 來生成自其而下的所有分支。
擴展金鑰 中提供的金鑰可以是 私鑰 或者 公鑰,和 鏈碼 結合起來分別稱為 擴展私鑰(Extended Private Key) 和 擴展公鑰(Extended Public Key),並且分別記為 (k, c) 和 (K, c),其中公鑰 K = point(k)。
我們可以從 擴展私鑰 推導出 擴展公鑰,而反之則不可以,因此對於某些交易場景(如電商),可以為每筆交易生成一個新的公鑰和地址來收款,而擴展私鑰可以被儲存在紙質錢包或者硬體錢包中,用於安全的離線簽署交易。可以看到 擴展公鑰 的安全性相對高一些,下图為透過 擴展 父公鑰 來衍生 子私鑰進而生成子公鑰 的傳遞機制: