精通比特幣(第五章)【錢包】

風靈使發表於2018-10-09

“錢包”一詞在比特幣中有多重含義。
廣義上,錢包是一個應用程式,為使用者提供互動介面。 錢包控制使用者訪問許可權,管理金鑰和地址,跟蹤餘額以及建立和簽名交易。
狹義上,即從程式設計師的角度來看,“錢包”是指用於儲存和管理使用者金鑰的資料結構。
我們將深入介紹第二層含義,本章中錢包是私鑰的容器,一般是通過結構化檔案或簡單資料庫來實現。

5.1錢包技術概述

在本節中,我們總結了各種技術,它們為使用者構建起友好,安全和靈活的比特幣錢包。

一個常見誤解是,比特幣錢包裡含有比特幣。 事實上,錢包裡只含有鑰匙。 “錢幣”被記錄在比特幣網路的區塊鏈中。 使用者通過錢包中的金鑰簽名交易,從而來控制網路上的錢幣。 在某種意義上,比特幣錢包是金鑰鏈。

提示比特幣錢包只含有金鑰,而不是錢幣。 每個使用者有一個包含多個金鑰的錢包。 錢包只包含私鑰/公鑰對的金鑰鏈(請參閱[私鑰章節])。 使用者用金鑰簽名交易,從而證明他們擁有交易輸出(他們的錢幣)。 錢幣以交易輸出的形式儲存在區塊鏈中(通常記為vout或txout)。

有兩種主要型別的錢包,區別在於它們包含的多個金鑰是否相互關聯。

第一種型別是非確定性錢包(nondeterministic wallet),其中每個金鑰都是從隨機數獨立生成的。金鑰彼此無關。這種錢包也被稱為“Just a Bunch Of Keys(一堆金鑰)”,簡稱JBOK錢包。

第二種型別是確定性錢包(deterministic wallet),其中所有的金鑰都是從一個主金鑰派生出來,這個主金鑰即為種子(seed)。該型別錢包中所有金鑰都相互關聯,如果有原始種子,則可以再次生成全部金鑰。確定性錢包中使用了許多不同的金鑰推導方法。最常用的推導方法是使用樹狀結構,稱為分級確定性錢包或HD錢包。

確定性錢包由種子衍生創造。為了便於使用,種子被編碼為英文單詞,也稱為助記詞。

接下來的幾節將深入介紹這些技術。

5.1.1非確定性(隨機)錢包

在最早的一批比特幣客戶端中( Bitcoin Core,現在稱作比特幣核心客戶端),錢包只是隨機生成的私鑰集合。這種型別的錢包被稱作零型非確定錢包。舉個例子,比 特幣核心客戶端預先生成100個隨機私鑰,從最開始就生成足夠多的私鑰並且每個金鑰只使用一次。這種錢包現在正在被確定性錢包替換,因為它們難以管理、 備份以及匯入。隨機金鑰的缺點就是如果你生成很多私鑰,你必須儲存它們所有的副本。這就意味著這個錢包必須被經常性 地備份。每一個金鑰都必須備份,否則一旦錢包不可訪問時,錢包所控制的資金就付之東流。這種情況直接與避免地址重複使用的原則相沖突——每個比特幣地址只能用一次交易。地址重複使用將多個交易和地址關聯在一起,這會減少隱私。當你想避免重複使用地址時,零型非確定性錢包並不是好的選擇,因為你要創造過多的私鑰並且要儲存它們。雖然比特幣核心客戶端包含零型錢包,但比特幣的核心開發者並不鼓勵大家使用。

圖5-1展示的是一個非確定性錢包,其含有的隨機金鑰是個鬆散的集合。

圖5-1表示包含有鬆散結構的隨機鑰匙的集合的非確定性錢包
提示除了簡單的測試之外,不要使用非確定性錢包。 它們對於備份和使用來說太麻煩了。 相反,推薦使用基於行業標準的HD錢包,可以用種子助記詞進行備份。

5.1.2 確定性(種子)錢包

確定性,或者“種子”錢包包含通過使用單項離散函式而可從公共的種子生成的私鑰。種子是隨機生成的數字。這個數字也含有比如索引號碼或者可生成私鑰的“鏈碼”(參見“ 分層確定性錢包(BIP0032/BIP0044)”一節)。在確定性錢包中,種子足夠恢復所有的已經產生的私鑰,所以只用在初始建立時的一個簡單備份就足以搞定。並且種子也足夠讓錢包匯入或者匯出。這就很容易允許使用者的私鑰在錢包之間輕鬆轉移。

圖5-2展示了確定性錢包的邏輯圖。

圖5-2確定性種子錢包:從種子派生的金鑰的確定性序列

5.1.3 分層確定性錢包(HD Wallets (BIP-32/BIP-44))

確定性錢包被開發成更容易從單個“種子”中生成許多金鑰。確定性錢包的最高階形式是通過BIP0032標準定義的HD錢包。HD錢包包含以樹狀結構衍生的金鑰,使得父金鑰可以衍生一系列子金鑰,每個子金鑰可以衍生出一系列孫金鑰,以此類推,無限衍生。圖5-3展示了樹狀結構。

圖5-3HD錢包:從種子產生的金鑰樹

相比較隨機(不確定性)金鑰,HD錢包有兩個主要的優勢。第一,樹狀結構可以被用來表達額外的組織含義。比如當一個特定分支的子金鑰被用來接收交易收入並且有另一個分支的子金鑰用來負責支付花費。不同分支的金鑰都可以被用在企業環境中,這就可以支配不同的分支部門、子公司、具體功能以及會計類別。

HD錢包的第二個好處是,使用者可以建立一系列公鑰,而不需要訪問對應的私鑰。這樣,HD錢包就能用在不安全的伺服器上,或者用在接收環境中,它為每個交易釋出一個不同的公鑰。公共鑰匙不需要被預先載入或者提前衍生,而在伺服器中不需要可用來支付的私鑰。

5.1.4種子和助記詞(BIP-39)

HD錢包具有管理多個金鑰和地址的強大機制。由一系列英文單詞生成種子是個標準化的方法,這樣易於在錢包中轉移、匯出和匯入,如果HD錢包與這種方法相結合,將會更加有用。 這些英文單詞被稱為助記詞,標準由BIP-39定義。 今天,大多數比特幣錢包(以及其他加密貨幣的錢包)使用此標準,並可以使用可互操作的助記詞匯入和匯出種子進行備份和恢復。

讓我們從實際的角度來看以下哪種種子更容易抄錄、閱讀、匯出以及匯入。

16進製表示的種子:

0C1E24E5917779D297E14D45F14E1A1A

助記詞表示的種子:

army van defense carry jealous true
garbage claim echo media make crunch

5.1.5錢包最佳實踐

由於比特幣錢包技術已經成熟,出現了一些常見的行業標準,使得比特幣錢包具備廣泛互操作,易於使用,安全和靈活的特性。這些常用的標準是:

助記碼,基於BIP-39

HD錢包,基於BIP-32

多用途HD錢包結構,基於BIP-43

多幣種和多帳戶錢包,基於BIP-44

這些標準可能會隨著發展而改變或過時,但是現在它們形成了一套互鎖技術,這些技術已成為比特幣的事實上的錢包標準。

這些標準已被廣泛的軟體和硬體比特幣錢包採用,使所有這些錢包互操作。使用者可以匯出在其中一個錢包上生成的助記符,並將其匯入另一個錢包,實現恢復所有交易,金鑰和地址。

列舉支援這些標準的軟體錢包,包括(按字母順序排列)Breadwallet,Copay,Multibit HD和Mycelium。列舉支援這些標準的硬體錢包,包括(按字母順序排列)Keepkey,Ledger和Trezor。

以下部分將詳細介紹這些技術。

提示如果您正準備開發一個比特幣錢包,那麼它應該被構建為一個HD錢包,一個種子被編碼為助記詞程式碼進行備份,遵循BIP-32,BIP-39,BIP-43BIP-44標準,下面章節有所涉獵。

5.1.6使用比特幣錢包

在[使用者故事]中,我們介紹了Gabriel,里約熱內盧是一個有進取心的少年,他正在經營一家簡單的網路商店,銷售比特幣品牌的T恤,咖啡杯和貼紙。

Gabriel使用Trezor比特幣硬體錢包(Trezor裝置:硬體HD錢包)來安全地管理他的比特幣。 Trezor是一個簡單的USB裝置,具有兩個按鈕,用於儲存金鑰*(以HD錢包的形式)和簽署交易。 Trezor錢包遵循*本章討論的所有行業標準,因此Gabriel不依賴於任何專有技術或單一供應商解決方案。

圖5-4Trezor硬體錢包

當Gabriel首次使用Trezor時,裝置從內建的硬體隨機數生成器生成助記詞和種子。 在這個初始化階段,錢包在螢幕上按順序逐個顯示單詞。

圖5-5Trezor會逐個顯示助記詞

通過寫下這個助記符,Gabriel建立了一個備份(參見表5-1),可以在Trezor裝置丟失或損壞的情況下用於恢復。 在新的Trezor錢包,或者任一種相容的軟體和硬體錢包中,助記詞都可以用於恢復。 請注意,單詞序列很重要,因此,記憶紙備份需要對每個單詞都有空格。Gabriel必須仔細記錄每個單詞的編號,以保持正確的順序。
表5-1Gabriel的助記器備份

表5-1Gabriel的助記器備份

提示為了簡單起見,Gabriel的助記詞記錄中顯示了一個12個詞。 事實上,大多數硬體錢包生成更安全的24個詞的助記符。 助記詞以完全相同的方式使用,不管長度如何。

作為網店的第一次實踐,Gabriel使用他的Trezor裝置生成一個比特幣地址。 所有客戶的訂單都使用此單一地址。 我們將看到,這種方法有一些缺點,不過可以使用HD錢包進行改進。

5.2錢包技術細節

現在我們來深入瞭解被眾多比特幣錢包所使用的重要的行業標準。

5.2.1助記碼詞彙(BIP-39)

助記碼詞彙是英文單詞序列代表(編碼)用作種子對應所確定性錢包的隨機數。單詞的序列足以重新建立種子,並且從 種子那裡重新創造錢包以及所有私鑰。在首次建立錢包時,帶有助記碼的,執行確定性錢包的錢包的應用程式將會向使用者展示一個12至24個詞的順序。單詞的順序就是錢包的備份。它也可以被用來恢復以及重新創造應用程式相同或者相容的錢包的金鑰。助記碼詞彙可以讓使用者複製錢包更容易一些,因為相比較隨機數字順序來說,它們更容易地被閱讀和正確抄寫。

提示助記詞經常與“腦錢包”混淆。 他們不一樣。主要區別在於腦錢包由使用者選擇的單片語成,而助記符是由錢包隨機建立的,並呈現給使用者。 這個重要的區別使助記詞更加安全,因為人類猜測隨機數還是無能為力。

助記碼被定義在比特幣的改進建議39中(參見"附錄2 比特幣改進協議[bip0039]”)。需要注意的是,BIP-39是助記碼標準的一個實施方案。還有一個不同的標準,使用一組不同的單詞,是由Electrum錢包使用,並且早於BIP-39BIP-39由Trezor硬體錢包背後的公司提出,與Electrum的實施不相容。 然而,BIP-39現在已經在數十個可互操作的實踐案例中獲得了廣泛的行業支援,應被視為事實上的行業標準。

BIP-39定義了助記符碼和種子的建立,我們在這裡描述了九個步驟。 為了清楚起見,該過程分為兩部分:

1-6步是建立助記詞,7-9步是從助記詞到種子。

5.2.2建立助記詞

助記詞是由錢包使用BIP-39中定義的標準化過程自動生成的。 錢包從熵源開始,增加校驗和,然後將熵對映到單詞列表:

1、建立一個128到256位的隨機序列(熵)。

2、提出SHA256雜湊前幾位(熵長/ 32),就可以創造一個隨機序列的校驗和。

3、將校驗和新增到隨機序列的末尾。

4、將序列劃分為包含11位的不同部分。

5、將每個包含11位部分的值與一個已經預先定義2048個單詞的字典做對應。

6、生成的有順序的單片語就是助記碼。

圖5-6展示了熵如何生成助記詞。

圖5-6表示生成熵和編碼作為助記詞

表5-2表示了熵資料的大小和助記詞的長度之間的關係。

表5-2助記碼:熵及欄位長度

5.2.3從助記詞生成種子

助記詞表示長度為128至256位的熵。 通過使用金鑰延伸函式PBKDF2,熵被用於匯出較長的(512位)種子。將所得的種子用於構建確定性錢包並得到其金鑰。

金鑰延伸函式有兩個引數:助記詞和鹽。其中鹽的目的是增加構建能夠進行暴力攻擊的查詢表的困難度。 在BIP-39標準中,鹽具有另一目的,它允許引入密碼短語(passphrase),作為保護種子的附加安全因素,我們將在BIP-39可選密碼短語章節詳細地描述。

建立助記詞之後的7-9步是:

7、PBKDF2金鑰延伸函式的第一個引數是從步驟6生成的助記符。

8、PBKDF2金鑰延伸函式的第二個引數是鹽。 由字串常數“助記詞”與可選的使用者提供的密碼字串連線組成。

9、PBKDF2使用HMAC-SHA512演算法,使用2048次雜湊來延伸助記符和鹽引數,產生一個512位的值作為其最終輸出。 這個512位的值就是種子。

圖5-7顯示了從助記詞如何生成種子
圖5-7顯示了從助記詞如何生成種子

提示 金鑰延伸函式,使用2048次雜湊是一種非常有效的保護,可以防止對助記詞或密碼短語的暴力攻擊。 它使得攻擊嘗試非常昂貴(從計算的角度),需要嘗試超過幾千個密碼和助記符組合,而這樣可能產生的種子的數量是巨大的(2^512)。

表5-3、5-4和表5-5展示了一些助記碼的例子和它所生成的種子。

表5-3 128位熵的助記碼,沒有密碼短語所產生的種子

表5-4 128位熵的助記碼,增加密碼短語所產生的種子

表5-5 256位熵的助記碼,沒有密碼短語所產生的種子

5.2.4BIP-39中的可選密碼短語

BIP-39標準允許在推導種子時使用可選的密碼短語。 如果沒有使用密碼短語,助記詞是用由常量字串“助記詞”構成的鹽進行延伸,從任何給定的助記詞產生一個特定的512位種子。 如果使用密碼短語,金鑰延伸函式使用同樣的助記詞也會產生不同的種子。事實上,給予一個單一的助記詞,每一個可能的密碼短語都會導致不同的種子。 基本上沒有“錯誤”的密碼短語, 所有密碼短語都是有效的,它們都會導致不同的種子,形成一大批可能未初始化的錢包。這批錢包非常之大(2^512),使用暴力破解或隨機猜測基本不可能。

提示BIP-39中沒有“錯誤的”密碼短語。 每個密碼都會導致一些錢包,只是未使用的錢包是空的。

可選密碼短語帶來兩個重要功能:

(儲存在大腦中的)密碼短語成為第二個因素,使得助記詞不能單獨使用,避免了助記詞備份盜取後被利用。
起到掩人耳目的效果,把密碼短語指向有小額資金的錢包,分散攻擊者注意力,使其不在關注擁有大額資金的“真實”錢包。

然而,需要注意的是,使用密碼短語也會引起丟失的風險:

如果錢包所有者無行為能力或死亡,沒有人知道密碼,種子是無用的,所有儲存在錢包中的資金都將永遠丟失。相反,如果所有者將密碼短語與種子備份在相同的地方,則違反了上述第二個因素的目的。雖然密碼是非常有用的,但它們只能與仔細計劃的備份和恢復流程結合使用,考慮到所有者個人風險的可能性,應該允許其家人恢復加密資產。

5.2.5使用助記符程式碼

BIP-39被做成函式庫,支援多種程式語言:

python-mnemonic

SatoshiLabs團隊在Python中提出了BIP-39標準的參考實現

bitcoinjs/bip39

作為流行的bitcoinJS框架的一部分,在JavaScript中實現了BIP-39

libbitcoin/mnemonic

作為流行的Libbitcoin框架的一部分,在C ++中實現了BIP-39

還有一個BIP-39生成器在獨立的網頁中實現,對於測試和實驗非常有用。圖5-8展示一個獨立的網頁,可以生成助記詞、種子和擴充套件私鑰。

圖5-8BIP-39生成器在獨立的網頁中實現

BIP-39生成器可以離線使用,也可以使用這個線上地址.地址轉向到這兒了

5.3從種子中創造HD錢包

HD錢包從單個根種子(root seed)中建立,為128到256位的隨機數。最常見的是,這個種子是從助記符產生的,如上一節所述。

HD錢包的所有的確定性都衍生自這個根種子。任何相容HD 錢包的根種子也可重新創造整個HD錢包。所以簡單的轉移HD錢包的根種子就讓HD錢包中所包含的成千上百萬的金鑰被複制,儲存匯出以及匯入。

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

圖5-9從根種子建立主金鑰以及HD錢包的主鏈程式碼的過程

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

5.3.1私有子金鑰的衍生

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

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

一個母私鑰或者公共鑰匙(ECDSA未壓縮鍵)

一個叫做鏈碼(256 bits)的種子

一個索引號(32 bits)

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

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

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

圖5-10延長母私鑰去創造子私鑰

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

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

圖5-11闡述了擴充套件母公鑰來衍生子公鑰的傳遞機制。

圖5-11擴充套件母公共鑰匙來創造一個子公共鑰匙

5.3.2使用衍生的子金鑰

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

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

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

5.3.3擴充套件金鑰

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

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

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

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

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

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

xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c

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

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9

5.3.4公共子金鑰推導

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

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

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

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

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

5.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裝置才能匯出公鑰。請注意,硬體錢包永遠不會匯出私鑰,這些金鑰始終保留在裝置上。圖5-12顯示了Gabriel用於匯出xpub的Web介面。

圖5-12從Trezor硬體錢包匯出xpub

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

5.3.6硬化子金鑰的衍生

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

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

圖5-13子金鑰的硬化推導;,省略父公鑰

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

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

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

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

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

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

HD錢包中的金鑰是用“路徑”命名的,且每個級別之間用斜槓(/)字元來表示(見表5-6)。由主私鑰衍生出的私鑰起始以“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個子金鑰。

表5-6 HD錢包路徑的例子

5.3.9HD錢包樹狀結構的導航

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展示了更多的例子。

表5-7 BIP0044 HD 錢包結構的例子

相關文章