如何從種子中創造HD錢包

買賣虛擬貨幣
HD錢包從單個根種子(root seed)中建立,為128到256位的隨機數。最常見的是,這個種子是從助記符產生的,如上一節所述。HD錢包的所有的確定性都衍生自這個根種子。任何相容HD 錢包的根種子也可重新創造整個HD錢包。所以簡單的轉移HD錢包的根種子就讓HD錢包中所包含的成千上百萬的金鑰被複制,儲存匯出以及匯入。

下圖展示建立主金鑰以及HD錢包的主鏈程式碼的過程。

根種子輸入到HMAC-SHA512演算法中就可以得到一個可用來創造主私鑰(m)(master private key(m) )和主鏈程式碼(a master chain code)的雜湊。主私鑰(m)之後可以透過使用我們在本章先前看到的那個普通橢圓曲線m * G過程生來成相對應的主公鑰(M)。 鏈程式碼用於從母金鑰中創造子金鑰的那個函式中引入熵。如下一節所示。

1. 私有子金鑰的衍生

分層確定性錢包使用CKD(child key derivation)函式去從母金鑰衍生出子金鑰。

子金鑰衍生函式是基於單項雜湊函式。這個函式結合了:

一個母私鑰或者公共鑰匙(ECDSA未壓縮鍵)
一個叫做鏈碼(256 bits)的種子
一個索引號(32 bits)

鏈碼是用來給這個過程引入確定性隨機資料的,使得索引不能充分衍生其他的子金鑰。因此,有了子金鑰並不能讓它發現自己的姊妹金鑰,除非你已經有了鏈碼。最初的鏈碼種子(在密碼樹的根部)是用隨機資料構成的,隨後鏈碼從各自的母鏈碼中衍生出來。

這三個專案(母私鑰,鏈碼,索引)相結合並雜湊可以生成子金鑰,如下。

母公共鑰匙——鏈碼——以及索引號合併在一起並且用HMAC-SHA512函式雜湊之後可以產生512位的雜湊。所得的雜湊可被拆分為兩部分。雜湊右半部分的256位產出可以給子鏈當鏈碼。左半部分256位雜湊以及索引碼被載入在母私鑰上來衍生子私鑰。在圖2中,我們看到這個說明——索引集被設為0去生產母金鑰的第0個子金鑰(第一個透過索 引)。

改變索引可以讓我們延長母金鑰以及創造序列中的其他子金鑰。比如子0,子1,子2等等。每一個母金鑰可以有2,147,483,647 (2^31) 個子金鑰。2^31是整個2^32範圍可用的一半,因為另一半是為特定型別的推導而保留的,我們將在本章稍後討論。

向密碼樹下一層重複這個過程,每個子金鑰可以依次成為母金鑰繼續創造它自己的子金鑰,直到無限代。

2. 使用衍生的子金鑰

子私鑰不能從非確定性(隨機)金鑰中被區分出來。因為衍生函式是單向的,所以子金鑰不能被用來發現他們的母金鑰。子金鑰也不能用來發現他們的相同層級的姊妹金鑰。如果你有第n個子金鑰,你不能發現它前面的(第n-1)或者 後面的子金鑰(n+1)或者在同一順序中的其他子金鑰。只有母金鑰以及鏈碼才能得到所有的子金鑰。沒有子鏈碼的話,子金鑰也不能用來衍生出任何孫金鑰。你需要同時有子金鑰以及對應的鏈碼才能建立一個新的分支來衍生出孫金鑰。

那子私鑰自己可被用做什麼呢?它可以用來做公鑰和比特幣地址。之後它就可以被用在那個地址來簽署交易和支付任何東西。

提示子私鑰、對應的公鑰以及比特幣地址都不能從隨機創造的金鑰和地址中被區分出來。事實是它們所在的序列,在創造他們的HD錢包函式之外是不可見的。一旦被創造出來,它們就和“正常”金鑰一樣執行了。

3. 擴充套件金鑰

正如我們之前看到的,金鑰衍生函式可以被用來創造金鑰樹上任何層級的子金鑰。這隻需要三個輸入量:一個金鑰,一個鏈碼以及想要的子金鑰的索引。金鑰以及鏈碼這兩個重要的部分被結合之後,就叫做擴充套件金鑰(extended key)。術語“extended key”也被認為是“可擴充套件的金鑰”,因為這種金鑰可以用來衍生子金鑰。

擴充套件金鑰可以簡單地被儲存並且表示為簡單的將256位金鑰與256位鏈碼所並聯的512位序列。有兩種擴充套件金鑰。擴充套件的私鑰是私鑰以及鏈碼的結合。它可被用來衍生子私鑰(子私鑰可以衍生子公鑰)。公鑰以及鏈碼組成擴充套件公鑰,它可以用來擴充套件子公鑰,見“生成公鑰”章節。

想象一個擴充套件金鑰作為HD錢包中金鑰樹結構的一個分支的根。你可以衍生出這個分支的剩下所有部分。擴充套件私鑰可以建立一個完整的分支,而擴充套件公鑰只能夠創造一個公鑰的分支。

提示一個擴充套件金鑰包括一個私鑰(或者公鑰)以及一個鏈碼。一個擴充套件金鑰可以創造出子金鑰並且能創造出金鑰樹結構中的整個分支。分享擴充套件金鑰就可以訪問整個分支。

擴充套件金鑰透過Base58Check來編碼,從而能輕易地在不同的BIP-32相容錢包之間匯入匯出。擴充套件金鑰編碼用的 Base58Check使用特殊的版本號,這導致在Base58編碼字元中,出現字首“xprv”和“xpub”。這種字首可以讓編碼更易被識別。因為擴充套件金鑰是512或者513位,所以它比我們之前所看到的Base58Check編碼串更長一些。

以下面的擴充套件私鑰為例,其使用的是Base58Check編碼:

xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c

這是上面擴充套件私鑰對應的擴充套件公鑰,同樣使用Base58Check編碼:

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9

4. 公共子金鑰推導

正如之前提到的,分層確定性錢包的一個很有用的特點就是可以不透過私鑰而直接從公共母金鑰派生出公共子金鑰的能 力。這就給了我們兩種衍生子公鑰的方法:或者透過子私鑰,再或者就是直接透過母公鑰。

因此,擴充套件金鑰可以在HD錢包結構的分支中,被用來衍生所有的公鑰(且只有公鑰)。

這種快捷方式可以用來創造非常保密的只有公鑰配置。在配置中,伺服器或者應用程式不管有沒有私鑰,都可以有擴充套件公鑰的副本。這種配置可以創造出無限數量的公鑰以及比特幣地址。但是傳送到這個地址裡的任何比特幣都不能使用。與此同時,在另一種更保險的伺服器上,擴充套件私鑰可以衍生出所有的對應的可簽署交易以及花錢的私鑰。

這種方案的常見應用是安裝擴充套件公鑰電商的網路伺服器上。網路伺服器可以使用這個公鑰衍生函式去給每一筆交易(比如客戶的購物車)創造一個新的比特幣地址。但為了避免被偷,網路服務商不會有任何私鑰。沒有HD錢包的話,唯一的方法就是在不同的安全伺服器上創造成千上萬個比特幣地址,之後就提前上傳到電商伺服器上。這種方法比較繁瑣而且要求持續的維護來確保電商伺服器不“用光”公鑰。

這種解決方案的另一種常見的應用是冷藏或者硬體錢包。在這種情況下,擴充套件的私鑰可以被儲存在紙質錢包中或者硬體裝置中(比如 Trezor 硬體錢包),與此同時擴充套件公鑰可以線上儲存。使用者可以根據意願創造“接收”地址而私鑰可以安全地線上下被儲存。為了支付資金,使用者可以使用擴充套件的私鑰離線簽署比特幣客戶或者透過硬體錢包裝置(比如 Trezor)簽署交易。圖3闡述了擴充套件母公鑰來衍生子公鑰的傳遞機制。

5. 在網店中使用擴充套件公鑰(xpub)

繼續Gabriel網店的故事,讓我們看看Gabriel是如何使用HD錢包。

Gabriel在一個網路上的託管伺服器上建立一個簡單的WordPress頁面,作為他的網上商店。它的網店非常簡單,只有幾個頁面和一張帶有一個比特幣地址的訂單。

Gabriel使用他的Trezor裝置生成的第一個比特幣地址作為他的商店的主要比特幣地址。這樣,所有收到的付款都將支付給他的Trezor硬體錢包所控制的地址。

客戶可以使用表格提交訂單,並向Gabriel釋出的比特幣地址傳送付款,觸發一封電子郵件,其中包含Gabriel的訂單詳細資訊。每週只幾個訂單,這個系統執行得很好。

然而,這個小型網路商店變得相當成功,並吸引了很多來自當地社羣的訂單。Gabriel很快就不堪重負。由於所有訂單都支付相同的地址,因此很難正確匹配訂單和交易,特別是當同一數量的多個訂單緊密相連時。

HD錢包可以在不知道私鑰的情況下獲取公共子金鑰,該能力為Gabriel提供了更好的解決方案。 Gabriel可以在他的網站上載入一個擴充套件公鑰(xpub),這可以用於為每個客戶訂單匯出唯一的地址。Gabriel可以花費他在Trezor裡資金,但載入在網站上的xpub只能生成地址並收到資金。HD錢包的這個功能非常安全。 Gabriel的網站不包含任何私鑰,因此不需要高階別的安全性。

為了匯出xpub,Gabriel將基於Web的軟體與Trezor硬體錢包配合使用。必須插入Trezor裝置才能匯出公鑰。請注意,硬體錢包永遠不會匯出私鑰,這些金鑰始終保留在裝置上。下圖顯示了Gabriel用於匯出xpub的Web介面。

Gabriel將xpub複製到他的網店的比特幣購物軟體中。 他使用的軟體是Mycelium Gear,它是一個網店的開源外掛,用於各種網路託管和內容平臺。 Mycelium Gear使用xpub為每次購買生成一個唯一的地址。

6. 硬化子金鑰的衍生

從擴充套件公鑰衍生一個分支公鑰的能力是很重要的,但牽扯一些風險。訪問擴充套件公鑰並不能得到訪問子私鑰的途徑。但是,因為擴充套件公鑰包含有鏈碼,如果子私鑰被知道或者被洩漏的話,鏈碼就可以被用來衍生所有的其他子私鑰。簡單地洩露的私鑰以及一個母鏈碼,可以暴露所有的子金鑰。更糟糕的是,子私鑰與母鏈碼可以用來推斷母私鑰。

為了應對這種風險,HD錢包使用一種叫做硬化衍生(hardened derivation)的替代衍生函式。這就“打破”了母公鑰以及子鏈碼之間的關係。這個硬化衍生函式使用了母私鑰去推導子鏈碼,而不是母公鑰。這就在母/子順序中創造了一道“防火牆”——有鏈碼但並不能夠用來推運算元鏈碼或者姊妹私鑰。強化衍生函式看起來幾乎與一般的衍生的子私鑰相同,不同的是母私鑰被用來輸入雜湊函式中而不是母公鑰,如圖所示。

當強化私鑰衍生函式被使用時,得到的子私鑰以及鏈碼與使用一般衍生函式所得到的結果完全不同。得到的金鑰“分支”可以被用來生產不易被攻擊的擴充套件公鑰,因為它所含的鏈碼不能被用來開發或者暴露任何私鑰。強化衍生也因此被用在上一層級,使用擴充套件公鑰的金鑰樹中創造“間隙”。

簡單地來說,如果你想要利用擴充套件公鑰的便捷來衍生公鑰的分支而不將你自己暴露在洩露擴充套件鏈碼的風險下, 你應該從強化母私鑰衍生公鑰,而不是從一般的母私鑰來衍生。最好的方式是,為了避免了推到出主金鑰,主金鑰所衍生的第一層級的子金鑰最好使用強化衍生。

7. 正常衍生和強化衍生的索引號碼

用在衍生函式中的索引號碼是32位的整數。為了區分金鑰是從正常衍生函式中衍生出來還是從強化衍生函式中產出,這個索引號被分為兩個範圍。索引號在0和2^31–1(0x0 to 0x7FFFFFFF)之間的是隻被用在常規衍生。索引號在2^31和2^32– 1(0x80000000 to 0xFFFFFFFF)之間的只被用在強化衍生。因此,索引號小於2^31就意味著子金鑰是常規的,而大於或者等於2^31的子金鑰就是強化型的。

為了讓索引號碼更容易被閱讀和展示,強化子金鑰的索引號碼是從0開始展示的,但是右上角有一個小撇號。第一個常規子金鑰因此被表述為0,但是第一個強化子金鑰(索引號為0x80000000)就被表示為0'。第二個強化金鑰依序有了索 引號0x80000001,且被顯示為1',以此類推。當你看到HD錢包索引號i',這就意味著 2^31+i。

8. HD錢包金鑰識別符(路徑)

HD錢包中的金鑰是用“路徑”命名的,且每個級別之間用斜槓(/)字元來表示。由主私鑰衍生出的私鑰起始以“m”打頭。由主公鑰衍生的公鑰起始以“M“打頭。因此,母金鑰生成的第一個子私鑰是m/0。第一個公鑰是M/0。第一個子金鑰的子金鑰就是m/0/1,以此類推。

金鑰的“祖先”是從右向左讀,直到你達到了衍生出的它的主金鑰。舉個例子,識別符號m/x/y/z描述的是子金鑰m/x/y的第z個子金鑰。而子金鑰m/x/y又是m/x的第y個子金鑰。m/x又是m的第x個子金鑰。

9. HD錢包樹狀結構的導航

HD錢包樹狀結構提供了極大的靈活性。每一個母擴充套件金鑰有40億個子金鑰:20億個常規子金鑰和20億個強化子金鑰。 而每個子金鑰又會有40億個子金鑰並且以此類推。只要你願意,這個樹結構可以無限類推到無窮代。但是,又由於有了這個靈活性,對無限的樹狀結構進行導航就變得異常困難。尤其是對於在不同的HD錢包之間進行轉移交易,因為內部組織到內部分支以及亞分支的可能性是無窮的。

兩個比特幣改進建議(BIPs)提供了這個複雜問題的解決辦法——透過建立幾個HD錢包樹的提議標準。BIP-43提出使用第一個強化子索引作為特殊的識別符號表示樹狀結構的“purpose”。基於BIP-43,HD錢包應該使用且只用第一層級的樹的分支,而且有索引號碼去識別結構並且有名稱空間來定義剩餘的樹的目的地。舉個例子,HD錢包只使用分支m/i'/是 為了表明那個被索引號“i”定義的特殊為目地。

在BIP-43標準下,為了延長的那個特殊規範,BIP-44提議了多賬戶結構作為“purpose”。所有遵循BIP-44的HD錢包依據只使用樹的第一個分支的要求而被定義:m/44'/。 BIP-44指定了包含5個預定義樹狀層級的結構:

m / purpose' / coin_type' / account' / change / address_index

第一層的purpose總是被設定為44'。

第二層的“coin_type”特指幣種並且允許多元貨幣HD錢包中的貨幣在第二個層級下有自己的亞樹狀結構。目前有三種貨幣被定義:Bitcoin is m/44'/0'、Bitcoin Testnet is m/44'/1',以及 Litecoin is m/44'/2'。

樹的第三層級是“account”,這可以允許使用者為了會計或者組織目的,而去再細分他們的錢包到獨立的邏輯性亞賬戶。 舉個例子,一個HD錢包可能包含兩個比特幣“賬戶”:m/44'/0'/0' 和 m/44'/0'/1'。每個賬戶都是它自己亞樹的根。

第四層級就是“change”。每一個HD錢包有兩個亞樹,一個是用來接收地址一個是用來創造找零地址。注意無論先前的層級是否使用強化衍生,這一層級使用的都是常規衍生。這是為了允許這一層級的樹可以在不安全環境下,輸出擴充套件公鑰。

被HD錢包衍生的可用的地址是第四層級的子級,就是第五層級的樹的“address_index”。比如,第三個層級的主賬戶收到比特幣支付的地址就是 M/44'/0'/0'/0/2。表5-7展示了更多的例子。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;