HD錢包從單個(gè)根種子(root seed)中創(chuàng)建,為128到256位的隨機(jī)數(shù)。
HD錢包的所有的確定性都衍生自這個(gè)根種子。任何兼容HD 錢包的根種子也可重新創(chuàng)造整個(gè)HD錢包。所以簡(jiǎn)單的轉(zhuǎn)移HD錢包的根種子就讓HD錢包中所包含的成千上百萬的密鑰被復(fù)制,儲(chǔ)存導(dǎo)出以及導(dǎo)入。
下圖展示創(chuàng)建主密鑰以及HD錢包的主鏈代碼的過程。
根種子輸入到HMAC-SHA512算法中就可以得到一個(gè)可用來創(chuàng)造主私鑰(m)(master private key(m) )和主鏈代碼(a master chain code)的哈希。主私鑰(m)之后可以通過使用我們?cè)诒菊孪惹翱吹降哪莻€(gè)普通橢圓曲線m * G過程生來成相對(duì)應(yīng)的主公鑰(M)。 鏈代碼用于從母密鑰中創(chuàng)造子密鑰的那個(gè)函數(shù)中引入熵。如下一節(jié)所示。
1. 私有子密鑰的衍生
分層確定性錢包使用CKD(child key derivation)函數(shù)去從母密鑰衍生出子密鑰。
子密鑰衍生函數(shù)是基于單項(xiàng)哈希函數(shù)。這個(gè)函數(shù)結(jié)合了:
一個(gè)母私鑰或者公共鑰匙(ECDSA未壓縮鍵)
一個(gè)叫做鏈碼(256 bits)的種子
一個(gè)索引號(hào)(32 bits)
鏈碼是用來給這個(gè)過程引入確定性隨機(jī)數(shù)據(jù)的,使得索引不能充分衍生其他的子密鑰。因此,有了子密鑰并不能讓它發(fā)現(xiàn)自己的姊妹密鑰,除非你已經(jīng)有了鏈碼。最初的鏈碼種子(在密碼樹的根部)是用隨機(jī)數(shù)據(jù)構(gòu)成的,隨后鏈碼從各自的母鏈碼中衍生出來。
這三個(gè)項(xiàng)目(母私鑰,鏈碼,索引)相結(jié)合并散列可以生成子密鑰,如下。
母公共鑰匙——鏈碼——以及索引號(hào)合并在一起并且用HMAC-SHA512函數(shù)散列之后可以產(chǎn)生512位的散列。所得的散列可被拆分為兩部分。散列右半部分的256位產(chǎn)出可以給子鏈當(dāng)鏈碼。左半部分256位散列以及索引碼被加載在母私鑰上來衍生子私鑰。在圖2中,我們看到這個(gè)說明——索引集被設(shè)為0去生產(chǎn)母密鑰的第0個(gè)子密鑰(第一個(gè)通過索 引)。
改變索引可以讓我們延長(zhǎng)母密鑰以及創(chuàng)造序列中的其他子密鑰。比如子0,子1,子2等等。每一個(gè)母密鑰可以有2,147,483,647 (2^31) 個(gè)子密鑰。2^31是整個(gè)2^32范圍可用的一半,因?yàn)榱硪话胧菫樘囟愋偷耐茖?dǎo)而保留的,我們將在本章稍后討論。
向密碼樹下一層重復(fù)這個(gè)過程,每個(gè)子密鑰可以依次成為母密鑰繼續(xù)創(chuàng)造它自己的子密鑰,直到無限代。
2. 使用衍生的子密鑰
子私鑰不能從非確定性(隨機(jī))密鑰中被區(qū)分出來。因?yàn)檠苌瘮?shù)是單向的,所以子密鑰不能被用來發(fā)現(xiàn)他們的母密鑰。子密鑰也不能用來發(fā)現(xiàn)他們的相同層級(jí)的姊妹密鑰。如果你有第n個(gè)子密鑰,你不能發(fā)現(xiàn)它前面的(第n-1)或者 后面的子密鑰(n+1)或者在同一順序中的其他子密鑰。只有母密鑰以及鏈碼才能得到所有的子密鑰。沒有子鏈碼的話,子密鑰也不能用來衍生出任何孫密鑰。你需要同時(shí)有子密鑰以及對(duì)應(yīng)的鏈碼才能創(chuàng)建一個(gè)新的分支來衍生出孫密鑰。
那子私鑰自己可被用做什么呢?它可以用來做公鑰和比特幣地址。之后它就可以被用在那個(gè)地址來簽署交易和支付任何東西。
提示子私鑰、對(duì)應(yīng)的公鑰以及比特幣地址都不能從隨機(jī)創(chuàng)造的密鑰和地址中被區(qū)分出來。事實(shí)是它們所在的序列,在創(chuàng)造他們的HD錢包函數(shù)之外是不可見的。一旦被創(chuàng)造出來,它們就和“正?!泵荑€一樣運(yùn)行了。
3. 擴(kuò)展密鑰
正如我們之前看到的,密鑰衍生函數(shù)可以被用來創(chuàng)造密鑰樹上任何層級(jí)的子密鑰。這只需要三個(gè)輸入量:一個(gè)密鑰,一個(gè)鏈碼以及想要的子密鑰的索引。密鑰以及鏈碼這兩個(gè)重要的部分被結(jié)合之后,就叫做擴(kuò)展密鑰(extended key)。術(shù)語“extended key”也被認(rèn)為是“可擴(kuò)展的密鑰”,因?yàn)檫@種密鑰可以用來衍生子密鑰。
擴(kuò)展密鑰可以簡(jiǎn)單地被儲(chǔ)存并且表示為簡(jiǎn)單的將256位密鑰與256位鏈碼所并聯(lián)的512位序列。有兩種擴(kuò)展密鑰。擴(kuò)展的私鑰是私鑰以及鏈碼的結(jié)合。它可被用來衍生子私鑰(子私鑰可以衍生子公鑰)。公鑰以及鏈碼組成擴(kuò)展公鑰,它可以用來擴(kuò)展子公鑰,見“生成公鑰”章節(jié)。
想象一個(gè)擴(kuò)展密鑰作為HD錢包中密鑰樹結(jié)構(gòu)的一個(gè)分支的根。你可以衍生出這個(gè)分支的剩下所有部分。擴(kuò)展私鑰可以創(chuàng)建一個(gè)完整的分支,而擴(kuò)展公鑰只能夠創(chuàng)造一個(gè)公鑰的分支。
提示一個(gè)擴(kuò)展密鑰包括一個(gè)私鑰(或者公鑰)以及一個(gè)鏈碼。一個(gè)擴(kuò)展密鑰可以創(chuàng)造出子密鑰并且能創(chuàng)造出密鑰樹結(jié)構(gòu)中的整個(gè)分支。分享擴(kuò)展密鑰就可以訪問整個(gè)分支。
擴(kuò)展密鑰通過Base58Check來編碼,從而能輕易地在不同的BIP-32兼容錢包之間導(dǎo)入導(dǎo)出。擴(kuò)展密鑰編碼用的 Base58Check使用特殊的版本號(hào),這導(dǎo)致在Base58編碼字符中,出現(xiàn)前綴“xprv”和“xpub”。這種前綴可以讓編碼更易被識(shí)別。因?yàn)閿U(kuò)展密鑰是512或者513位,所以它比我們之前所看到的Base58Check編碼串更長(zhǎng)一些。
以下面的擴(kuò)展私鑰為例,其使用的是Base58Check編碼:
xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c
這是上面擴(kuò)展私鑰對(duì)應(yīng)的擴(kuò)展公鑰,同樣使用Base58Check編碼:
xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9
4. 公共子密鑰推導(dǎo)
正如之前提到的,分層確定性錢包的一個(gè)很有用的特點(diǎn)就是可以不通過私鑰而直接從公共母密鑰派生出公共子密鑰的能 力。這就給了我們兩種衍生子公鑰的方法:或者通過子私鑰,再或者就是直接通過母公鑰。
因此,擴(kuò)展密鑰可以在HD錢包結(jié)構(gòu)的分支中,被用來衍生所有的公鑰(且只有公鑰)。
這種快捷方式可以用來創(chuàng)造非常保密的只有公鑰配置。在配置中,服務(wù)器或者應(yīng)用程序不管有沒有私鑰,都可以有擴(kuò)展公鑰的副本。這種配置可以創(chuàng)造出無限數(shù)量的公鑰以及比特幣地址。但是發(fā)送到這個(gè)地址里的任何比特幣都不能使用。與此同時(shí),在另一種更保險(xiǎn)的服務(wù)器上,擴(kuò)展私鑰可以衍生出所有的對(duì)應(yīng)的可簽署交易以及花錢的私鑰。
這種方案的常見應(yīng)用是安裝擴(kuò)展公鑰電商的網(wǎng)絡(luò)服務(wù)器上。網(wǎng)絡(luò)服務(wù)器可以使用這個(gè)公鑰衍生函數(shù)去給每一筆交易(比如客戶的購(gòu)物車)創(chuàng)造一個(gè)新的比特幣地址。但為了避免被偷,網(wǎng)絡(luò)服務(wù)商不會(huì)有任何私鑰。沒有HD錢包的話,唯一的方法就是在不同的安全服務(wù)器上創(chuàng)造成千上萬個(gè)比特幣地址,之后就提前上傳到電商服務(wù)器上。這種方法比較繁瑣而且要求持續(xù)的維護(hù)來確保電商服務(wù)器不“用光”公鑰。
這種解決方案的另一種常見的應(yīng)用是冷藏或者硬件錢包。在這種情況下,擴(kuò)展的私鑰可以被儲(chǔ)存在紙質(zhì)錢包中或者硬件設(shè)備中(比如 Trezor 硬件錢包),與此同時(shí)擴(kuò)展公鑰可以在線保存。使用者可以根據(jù)意愿創(chuàng)造“接收”地址而私鑰可以安全地在線下被保存。為了支付資金,使用者可以使用擴(kuò)展的私鑰離線簽署比特幣客戶或者通過硬件錢包設(shè)備(比如 Trezor)簽署交易。圖3闡述了擴(kuò)展母公鑰來衍生子公鑰的傳遞機(jī)制。
5. 在網(wǎng)店中使用擴(kuò)展公鑰(xpub)
繼續(xù)Gabriel網(wǎng)店的故事,讓我們看看Gabriel是如何使用HD錢包。
Gabriel在一個(gè)網(wǎng)絡(luò)上的托管服務(wù)器上建立一個(gè)簡(jiǎn)單的WordPress頁面,作為他的網(wǎng)上商店。它的網(wǎng)店非常簡(jiǎn)單,只有幾個(gè)頁面和一張帶有一個(gè)比特幣地址的訂單。
Gabriel使用他的Trezor設(shè)備生成的第一個(gè)比特幣地址作為他的商店的主要比特幣地址。這樣,所有收到的付款都將支付給他的Trezor硬件錢包所控制的地址。
客戶可以使用表格提交訂單,并向Gabriel發(fā)布的比特幣地址發(fā)送付款,觸發(fā)一封電子郵件,其中包含Gabriel的訂單詳細(xì)信息。每周只幾個(gè)訂單,這個(gè)系統(tǒng)運(yùn)行得很好。
然而,這個(gè)小型網(wǎng)絡(luò)商店變得相當(dāng)成功,并吸引了很多來自當(dāng)?shù)厣鐓^(qū)的訂單。Gabriel很快就不堪重負(fù)。由于所有訂單都支付相同的地址,因此很難正確匹配訂單和交易,特別是當(dāng)同一數(shù)量的多個(gè)訂單緊密相連時(shí)。
HD錢包可以在不知道私鑰的情況下獲取公共子密鑰,該能力為Gabriel提供了更好的解決方案。 Gabriel可以在他的網(wǎng)站上加載一個(gè)擴(kuò)展公鑰(xpub),這可以用于為每個(gè)客戶訂單導(dǎo)出唯一的地址。Gabriel可以花費(fèi)他在Trezor里資金,但加載在網(wǎng)站上的xpub只能生成地址并收到資金。HD錢包的這個(gè)功能非常安全。 Gabriel的網(wǎng)站不包含任何私鑰,因此不需要高級(jí)別的安全性。
為了導(dǎo)出xpub,Gabriel將基于Web的軟件與Trezor硬件錢包配合使用。必須插入Trezor設(shè)備才能導(dǎo)出公鑰。請(qǐng)注意,硬件錢包永遠(yuǎn)不會(huì)導(dǎo)出私鑰,這些密鑰始終保留在設(shè)備上。下圖顯示了Gabriel用于導(dǎo)出xpub的Web界面。
Gabriel將xpub復(fù)制到他的網(wǎng)店的比特幣購(gòu)物軟件中。 他使用的軟件是Mycelium Gear,它是一個(gè)網(wǎng)店的開源插件,用于各種網(wǎng)絡(luò)托管和內(nèi)容平臺(tái)。 Mycelium Gear使用xpub為每次購(gòu)買生成一個(gè)唯一的地址。
6. 硬化子密鑰的衍生
從擴(kuò)展公鑰衍生一個(gè)分支公鑰的能力是很重要的,但牽扯一些風(fēng)險(xiǎn)。訪問擴(kuò)展公鑰并不能得到訪問子私鑰的途徑。但是,因?yàn)閿U(kuò)展公鑰包含有鏈碼,如果子私鑰被知道或者被泄漏的話,鏈碼就可以被用來衍生所有的其他子私鑰。簡(jiǎn)單地泄露的私鑰以及一個(gè)母鏈碼,可以暴露所有的子密鑰。更糟糕的是,子私鑰與母鏈碼可以用來推斷母私鑰。
為了應(yīng)對(duì)這種風(fēng)險(xiǎn),HD錢包使用一種叫做硬化衍生(hardened derivation)的替代衍生函數(shù)。這就“打破”了母公鑰以及子鏈碼之間的關(guān)系。這個(gè)硬化衍生函數(shù)使用了母私鑰去推導(dǎo)子鏈碼,而不是母公鑰。這就在母/子順序中創(chuàng)造了一道“防火墻”——有鏈碼但并不能夠用來推算子鏈碼或者姊妹私鑰。強(qiáng)化衍生函數(shù)看起來幾乎與一般的衍生的子私鑰相同,不同的是母私鑰被用來輸入散列函數(shù)中而不是母公鑰,如圖所示。
當(dāng)強(qiáng)化私鑰衍生函數(shù)被使用時(shí),得到的子私鑰以及鏈碼與使用一般衍生函數(shù)所得到的結(jié)果完全不同。得到的密鑰“分支”可以被用來生產(chǎn)不易被攻擊的擴(kuò)展公鑰,因?yàn)樗逆湸a不能被用來開發(fā)或者暴露任何私鑰。強(qiáng)化衍生也因此被用在上一層級(jí),使用擴(kuò)展公鑰的密鑰樹中創(chuàng)造“間隙”。
簡(jiǎn)單地來說,如果你想要利用擴(kuò)展公鑰的便捷來衍生公鑰的分支而不將你自己暴露在泄露擴(kuò)展鏈碼的風(fēng)險(xiǎn)下, 你應(yīng)該從強(qiáng)化母私鑰衍生公鑰,而不是從一般的母私鑰來衍生。最好的方式是,為了避免了推到出主密鑰,主密鑰所衍生的第一層級(jí)的子密鑰最好使用強(qiáng)化衍生。
7. 正常衍生和強(qiáng)化衍生的索引號(hào)碼
用在衍生函數(shù)中的索引號(hào)碼是32位的整數(shù)。為了區(qū)分密鑰是從正常衍生函數(shù)中衍生出來還是從強(qiáng)化衍生函數(shù)中產(chǎn)出,這個(gè)索引號(hào)被分為兩個(gè)范圍。索引號(hào)在0和2^31–1(0x0 to 0x7FFFFFFF)之間的是只被用在常規(guī)衍生。索引號(hào)在2^31和2^32– 1(0x80000000 to 0xFFFFFFFF)之間的只被用在強(qiáng)化衍生。因此,索引號(hào)小于2^31就意味著子密鑰是常規(guī)的,而大于或者等于2^31的子密鑰就是強(qiáng)化型的。
為了讓索引號(hào)碼更容易被閱讀和展示,強(qiáng)化子密鑰的索引號(hào)碼是從0開始展示的,但是右上角有一個(gè)小撇號(hào)。第一個(gè)常規(guī)子密鑰因此被表述為0,但是第一個(gè)強(qiáng)化子密鑰(索引號(hào)為0x80000000)就被表示為0‘。第二個(gè)強(qiáng)化密鑰依序有了索 引號(hào)0x80000001,且被顯示為1’,以此類推。當(dāng)你看到HD錢包索引號(hào)i‘,這就意味著 2^31+i。
8. HD錢包密鑰識(shí)別符(路徑)
HD錢包中的密鑰是用“路徑”命名的,且每個(gè)級(jí)別之間用斜杠(/)字符來表示。由主私鑰衍生出的私鑰起始以“m”打頭。由主公鑰衍生的公鑰起始以“M“打頭。因此,母密鑰生成的第一個(gè)子私鑰是m/0。第一個(gè)公鑰是M/0。第一個(gè)子密鑰的子密鑰就是m/0/1,以此類推。
密鑰的“祖先”是從右向左讀,直到你達(dá)到了衍生出的它的主密鑰。舉個(gè)例子,標(biāo)識(shí)符m/x/y/z描述的是子密鑰m/x/y的第z個(gè)子密鑰。而子密鑰m/x/y又是m/x的第y個(gè)子密鑰。m/x又是m的第x個(gè)子密鑰。
9. HD錢包樹狀結(jié)構(gòu)的導(dǎo)航
HD錢包樹狀結(jié)構(gòu)提供了極大的靈活性。每一個(gè)母擴(kuò)展密鑰有40億個(gè)子密鑰:20億個(gè)常規(guī)子密鑰和20億個(gè)強(qiáng)化子密鑰。 而每個(gè)子密鑰又會(huì)有40億個(gè)子密鑰并且以此類推。只要你愿意,這個(gè)樹結(jié)構(gòu)可以無限類推到無窮代。但是,又由于有了這個(gè)靈活性,對(duì)無限的樹狀結(jié)構(gòu)進(jìn)行導(dǎo)航就變得異常困難。尤其是對(duì)于在不同的HD錢包之間進(jìn)行轉(zhuǎn)移交易,因?yàn)閮?nèi)部組織到內(nèi)部分支以及亞分支的可能性是無窮的。
兩個(gè)比特幣改進(jìn)建議(BIPs)提供了這個(gè)復(fù)雜問題的解決辦法——通過創(chuàng)建幾個(gè)HD錢包樹的提議標(biāo)準(zhǔn)。BIP-43提出使用第一個(gè)強(qiáng)化子索引作為特殊的標(biāo)識(shí)符表示樹狀結(jié)構(gòu)的“purpose”?;贐IP-43,HD錢包應(yīng)該使用且只用第一層級(jí)的樹的分支,而且有索引號(hào)碼去識(shí)別結(jié)構(gòu)并且有命名空間來定義剩余的樹的目的地。舉個(gè)例子,HD錢包只使用分支m/i’/是 為了表明那個(gè)被索引號(hào)“i”定義的特殊為目地。
在BIP-43標(biāo)準(zhǔn)下,為了延長(zhǎng)的那個(gè)特殊規(guī)范,BIP-44提議了多賬戶結(jié)構(gòu)作為“purpose”。所有遵循BIP-44的HD錢包依據(jù)只使用樹的第一個(gè)分支的要求而被定義:m/44‘/。 BIP-44指定了包含5個(gè)預(yù)定義樹狀層級(jí)的結(jié)構(gòu):
m / purpose’ / coin_type‘ / account’ / change / address_index
第一層的purpose總是被設(shè)定為44‘。
第二層的“coin_type”特指幣種并且允許多元貨幣HD錢包中的貨幣在第二個(gè)層級(jí)下有自己的亞樹狀結(jié)構(gòu)。目前有三種貨幣被定義:Bitcoin is m/44’/0‘、Bitcoin Testnet is m/44’/1‘,以及 Litecoin is m/44’/2‘。
樹的第三層級(jí)是“account”,這可以允許使用者為了會(huì)計(jì)或者組織目的,而去再細(xì)分他們的錢包到獨(dú)立的邏輯性亞賬戶。 舉個(gè)例子,一個(gè)HD錢包可能包含兩個(gè)比特幣“賬戶”:m/44’/0‘/0’ 和 m/44‘/0’/1‘。每個(gè)賬戶都是它自己亞樹的根。
第四層級(jí)就是“change”。每一個(gè)HD錢包有兩個(gè)亞樹,一個(gè)是用來接收地址一個(gè)是用來創(chuàng)造找零地址。注意無論先前的層級(jí)是否使用強(qiáng)化衍生,這一層級(jí)使用的都是常規(guī)衍生。這是為了允許這一層級(jí)的樹可以在不安全環(huán)境下,輸出擴(kuò)展公鑰。
被HD錢包衍生的可用的地址是第四層級(jí)的子級(jí),就是第五層級(jí)的樹的“address_index”。比如,第三個(gè)層級(jí)的主賬戶收到比特幣支付的地址就是 M/44’/0‘/0’/0/2。表5-7展示了更多的例子。
評(píng)論
查看更多