比特幣錢包涉及錢包程序和錢包文件。錢包程序創(chuàng)建公鑰來接受比特幣(satoshis)付款逐纬,并使用對(duì)應(yīng)的私鑰來花掉比特幣蛔屹。錢包文件保存私鑰和其他與錢包程序相關(guān)的交易信息(可選)。
錢包程序 Wallet Programs
允許接受和支付比特幣是錢包軟件的唯一功能豁生,但是一個(gè)特定的錢包程序不需要同時(shí)做這兩件事兔毒,兩個(gè)錢包程序可以一起工作,一個(gè)程序分發(fā)公鑰來接收比特幣甸箱,一個(gè)程序進(jìn)行交易簽名來支付這些比特幣育叁。
錢包程序也需要和peer-to-peer網(wǎng)絡(luò)進(jìn)行交互,以從區(qū)塊鏈中獲得信息并廣播出新的交易芍殖。當(dāng)然豪嗽,分發(fā)公鑰和交易簽名程序并不需要和peer-to-peer網(wǎng)絡(luò)本身進(jìn)行交互。
因此錢包系統(tǒng)(wallet system)就有三個(gè)必須的豌骏,但是缺可以獨(dú)立的部分:一個(gè)公鑰分發(fā)程序龟梦,一個(gè)簽名程序,一個(gè)聯(lián)網(wǎng)程序肯适。
NOTE: 這里說的是公鑰分發(fā)的通常情形变秦。在一些情況下,P2PKH和P2SH的散列值將被分發(fā)來代替公鑰的分發(fā)框舔,實(shí)際的公鑰只有在他們控制的output被支付時(shí)才分發(fā)蹦玫。
上面和下面說的輸出outputs赎婚,通常就是指 未使用的交易輸出 unspent transaction outputs 縮寫是UTXO,就是比特幣樱溉。
完整功能的錢包 Full-Service Wallets
最簡(jiǎn)單的錢包是一個(gè)執(zhí)行三個(gè)功能的程序:
- 生成私鑰挣输,并派生對(duì)應(yīng)的公鑰,并在需要時(shí)分發(fā)這些公鑰福贞;
- 監(jiān)控支付給這個(gè)公鑰的outputs撩嚼,在支付outputs時(shí),創(chuàng)建交易和進(jìn)行交易簽名挖帘;
- 廣播已經(jīng)完成簽名的交易完丽。
現(xiàn)在幾乎所有流行的BTC錢包都是Full-Service Wallets。
Full-Service Wallets的優(yōu)點(diǎn)是容易使用拇舀,單獨(dú)的一個(gè)程序可以完成用戶支付和接收比特幣的全部工作逻族。
Full-Service Wallets的缺點(diǎn)是,他們把私鑰保存在可以連接到Internet的設(shè)備上骄崩,因?yàn)槁?lián)網(wǎng)所以這樣的設(shè)備中的私鑰被攻擊會(huì)很容易聘鳞。
簽名錢包 Signing-Only Wallets
私鑰可以保存在一個(gè)在更安全環(huán)境中的單獨(dú)的錢包程序中來提高安全性,這些簽名錢包和可以與peer-to-peer網(wǎng)絡(luò)交互的聯(lián)網(wǎng)錢包配合使用要拂。
簽名錢包通常由確定性密鑰(deterministic key)創(chuàng)建抠璃,用來創(chuàng)建可以生成子公私鑰的父公私鑰。
當(dāng)?shù)谝淮芜\(yùn)行時(shí)脱惰,簽名錢包創(chuàng)建一個(gè)父私鑰搏嗡,并將對(duì)應(yīng)的公鑰傳輸給聯(lián)網(wǎng)錢包。
聯(lián)網(wǎng)錢包使用父公鑰派生出子公鑰拉一,幫助分發(fā)他們(可選的)彻况,監(jiān)控支付給這些公鑰的outputs,創(chuàng)建沒有簽名的支付交易舅踪,并把沒有簽名的支付交易傳輸給簽名錢包。
通常用戶有機(jī)會(huì)使用簽名錢包查看未簽名交易的詳情(尤其是outputs的詳情)良蛮。
在用戶查看步驟(可選的)之后抽碌,簽名錢包使用父私鑰派生相應(yīng)的子私鑰并進(jìn)行交易簽名,將簽名的交易傳回給聯(lián)網(wǎng)錢包决瞳。
聯(lián)網(wǎng)錢包把簽名的交易廣播到peer-to-peer網(wǎng)絡(luò)上货徙。
離線錢包 Offline Wallets
幾個(gè)full-service wallets也可以當(dāng)作兩個(gè)獨(dú)立的錢包使用:一個(gè)程序?qū)嵗?dāng)作簽名錢包(通常稱為“離線錢包”),另一個(gè)程序?qū)嵗?dāng)作聯(lián)網(wǎng)錢包(通常稱作在線錢包或者監(jiān)控錢包)皮胡。
脫機(jī)錢包在不聯(lián)網(wǎng)的設(shè)備上運(yùn)行痴颊,可以減少供給量。如果這種情況屡贺,通常由用戶來掌握所有數(shù)據(jù)的傳輸和使用可移動(dòng)設(shè)備比如USB驅(qū)動(dòng)器蠢棱。用戶的工作流是這樣的:
1.(離線)關(guān)閉設(shè)備上所有網(wǎng)絡(luò)連接锌杀,并安裝錢包軟件。以脫機(jī)模式啟動(dòng)軟件泻仙,創(chuàng)建父私鑰和父公鑰糕再,并賦值父公鑰到可移動(dòng)介質(zhì)上。
2.(在線)在另一臺(tái)設(shè)備上安裝錢包軟件玉转。這臺(tái)設(shè)備聯(lián)網(wǎng)突想,從可移動(dòng)介質(zhì)上導(dǎo)入父公鑰。下面的過程就像使用full-service wallet一樣究抓,分發(fā)公鑰來接收支付猾担。當(dāng)準(zhǔn)備消費(fèi)比特幣時(shí),填寫output詳情并把錢包生成的未簽名的交易保存到可移動(dòng)介質(zhì)上刺下。
3.(離線)在脫機(jī)實(shí)例中打開未簽名的交易绑嘹,審查交易的詳情,確保支付金額和地址正確怠李。這個(gè)可以阻止惡意軟件(malware)欺騙用戶簽署交易圾叼,從而支付給攻擊者。審查后捺癞,簽署交易并保存到可移動(dòng)介質(zhì)夷蚊。
4.(在線)在在線實(shí)例中打開已簽名的交易,以便廣播到peer-to-peer網(wǎng)絡(luò)髓介。
離線錢包的主要優(yōu)點(diǎn)在于同完整功能的錢包相比惕鼓,大大的提告了安全性。只要脫機(jī)錢包沒有被破壞(或者有缺陷)唐础,用戶在簽名之前會(huì)檢查所有支付的交易箱歧,即使在線錢包被破壞,用戶的比特幣也是安全的一膨。
離線錢包的主要缺點(diǎn)是麻煩呀邢,為了最大的安全性,要求用戶必須離線操作豹绪。任何時(shí)候要支付比特幣价淌,都必須啟動(dòng)離線設(shè)備,用戶必須從在線設(shè)備物理拷貝數(shù)據(jù)到離線設(shè)備并再從離線設(shè)備拷貝數(shù)據(jù)回在線設(shè)備瞒津。
硬件錢包 Hardware Wallets
硬件錢包是專門用于簽名的錢包設(shè)備蝉衣,一般是智能卡等安全芯片開發(fā)的設(shè)備。他們可以安全與其他聯(lián)網(wǎng)設(shè)備通信巷蚪,用戶也不需要手動(dòng)傳輸數(shù)據(jù)了病毡。硬件錢包的工作流程是這樣的:
- (硬件)生成父私鑰和公鑰,將硬件錢包連接到一個(gè)聯(lián)網(wǎng)設(shè)備上屁柏,這樣聯(lián)網(wǎng)設(shè)備就可以獲得父公鑰啦膜;
- (聯(lián)網(wǎng))像使用完整功能錢包一樣有送,分發(fā)公鑰來接收支付,當(dāng)準(zhǔn)備支付比特幣時(shí)功戚,填寫交易詳情娶眷,連接硬件錢包,然后點(diǎn)擊消費(fèi)啸臀,聯(lián)網(wǎng)錢包會(huì)將交易詳情發(fā)送給硬件錢包届宠;
- (硬件)查看硬件錢包屏幕上的交易詳情,一些硬件錢包可能會(huì)提示輸入PIN乘粒,硬件錢包對(duì)交易進(jìn)行簽名豌注,并將交易簽名返回給聯(lián)網(wǎng)錢包。
分發(fā)錢包 Distributing-Only Wallets
運(yùn)行再很難保證安全的環(huán)境中(比如web服務(wù)器)的錢包程序灯萍,只能設(shè)計(jì)成分發(fā)公鑰而不能有其他功能轧铁。這種簡(jiǎn)單的錢包有兩種常見的設(shè)計(jì)方法:
把大量的公鑰或者地址保存到數(shù)據(jù)庫中,然后根據(jù)請(qǐng)求分發(fā)一條數(shù)據(jù)庫內(nèi)的條目比如一個(gè)公鑰或者地址旦棉。為了避免重復(fù)使用密鑰齿风,web服務(wù)器應(yīng)該追蹤使用過的密鑰,并且永遠(yuǎn)不要用盡數(shù)據(jù)庫中的公鑰绑洛。
使用父公鑰創(chuàng)建子公鑰救斑。為了避免重復(fù)使用密鑰,必須使用一種方法確保一個(gè)公鑰不會(huì)被分發(fā)兩次真屯。
這兩種方法都不會(huì)增加大量的開銷脸候。
錢包文件 Wallet Files
比特幣錢包的核心是一組私鑰。這些集合被數(shù)字化的保存在一個(gè)文件中绑蔫,甚至可以保存在一張紙上运沦。
私鑰格式 Private Key Formats
私鑰是用來解鎖對(duì)應(yīng)公鑰地址的比特幣的。在比特幣中配深,標(biāo)準(zhǔn)格式的私鑰是一個(gè)256bit的數(shù)字携添,值在下列范圍內(nèi):
0x01 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140
這個(gè)范圍是由比特幣使用的secp256k1 ECDSA加密標(biāo)準(zhǔn)管理。
錢包導(dǎo)入格式 Wallet Import Format(WIF)
為了使得私鑰復(fù)制不容易出錯(cuò)篓叶,可以使用錢包導(dǎo)入格式WIF薪寓。WIF使用base58Check對(duì)私鑰進(jìn)行編碼,大大的降低了復(fù)制出錯(cuò)的機(jī)會(huì)澜共,就像標(biāo)準(zhǔn)比特幣地址一樣。
- 1.使用一個(gè)私鑰
- 2.在前面添加一個(gè)0x80作為mainnet地址锥腻,或者添加一個(gè)0xEF作為testnet地址嗦董;
- 3.如果他應(yīng)該和壓縮公鑰一起使用,在后面追加一個(gè)0x01.如果與未壓縮的公鑰一起使用瘦黑,則不會(huì)追加任何數(shù)據(jù)疚俱。
- 4.對(duì)擴(kuò)展后的密鑰進(jìn)行SHA-256哈希;
- 5.對(duì)SHA-256的結(jié)果進(jìn)行SHA-256哈希眠屎;
- 6.取第二個(gè)哈希結(jié)果的前4字節(jié)作為校驗(yàn)和迄委;
- 7.把從第5布獲得的校驗(yàn)和添加到第2步擴(kuò)展密鑰的末尾;
- 8.使用Base58Check編碼把第7步的數(shù)據(jù)轉(zhuǎn)換未Base58字符串喉童。
迷你私鑰格式 Mini Private Key Format
迷你私鑰格式是一種將私鑰編碼到30個(gè)字符以內(nèi)的方法,可以將密鑰嵌入到較小的物理空間中,比如物理比特幣Token懈贺,或者QR Code中。
- 1.迷你密鑰的第一個(gè)字符是‘S’坡垫;
- 2.為了確定私鑰格式良好梭灿,再私鑰上添加一個(gè)問號(hào);
- 3.計(jì)算SHA256哈希冰悠,如果產(chǎn)生的第一個(gè)字節(jié)是‘00’堡妒,他是格式良好的。密鑰的限制規(guī)則是一種輸入檢查typo-checking方法溉卓,用戶使用使用隨機(jī)數(shù)生成密鑰皮迟,直到生成格式良好的密鑰;
- 4.為了生成完整私鑰桑寨,用戶只需要獲取原始迷你私鑰的單個(gè)SHA256哈希值伏尼。這個(gè)過程是單向的,很難從生成密鑰計(jì)算出迷你私鑰格式西疤;
- 5.在很多實(shí)現(xiàn)中不允許字符‘1’出現(xiàn)在迷你私鑰中烦粒,因?yàn)樗c‘l’在視覺上相似;
上面寫的很別扭代赁,我回頭再整理一下扰她,重新寫一下。
公鑰格式 Public Key Formats
比特幣的ECDSA公鑰表示特定橢圓曲線上的一個(gè)點(diǎn)芭碍,比特幣使用的是secp256k1徒役。再傳統(tǒng)的未壓縮形式中,公鑰包含identification byte窖壕,一個(gè)32 bytes的X坐標(biāo)忧勿,一個(gè)32 bytes的Y坐標(biāo)。
下面一個(gè)超級(jí)簡(jiǎn)單的圖示意比特幣使用的橢圓曲線上的一個(gè)點(diǎn)瞻讽,
沿著曲線只有兩個(gè)點(diǎn)共享任何X坐標(biāo)鸳吸,所以只需要一個(gè)bit來表示Y坐標(biāo)的正負(fù)即可,也就是把Y坐標(biāo)壓縮成1bit速勇,這樣就在不改變?nèi)魏蝺?nèi)容的情況下晌砾,實(shí)現(xiàn)了接近50%的公鑰壓縮
使用這個(gè)壓縮公鑰不會(huì)丟失數(shù)據(jù),只需要使用少量運(yùn)算就可以重建Y坐標(biāo)并使用未壓縮的公鑰烦磁。在secp256官方文檔中描述了未壓縮和壓縮的公鑰养匈,廣泛使用的密碼算法庫一般都支持這兩種格式公鑰哼勇。
因?yàn)槿菀资褂茫麄儨p少了區(qū)塊鏈的空間呕乎,壓縮的公鑰是比特幣內(nèi)核Bitcoin Core的默認(rèn)值积担,也是所有比特幣軟件的推薦默認(rèn)值。
Bitcoin Core在0.6之前的版本猬仁,使用了未壓縮密鑰帝璧。這個(gè)造成一些復(fù)雜性。未壓縮的密鑰和壓縮的密鑰哈希形式不同逐虚。所以同一個(gè)密鑰適用兩個(gè)不同的P2PKH地址聋溜。這也就意味著在簽名腳本中密鑰必須以正確的格式提交,以便與前面輸出的公鑰腳本中的哈希值匹配叭爱。
因?yàn)檫@個(gè)原因撮躁,Bitcoin Core使用了幾個(gè)不同的identifier byte來幫助程序識(shí)別密鑰應(yīng)該如何使用:
- 與壓縮公鑰一起使用的私鑰在Base58編碼之前附加了0x01;
- 未壓縮的公鑰以0x04開頭买雾;壓縮的公鑰0x03或者0x02開頭把曼,這個(gè)前綴也在secp256k1
官方文檔中使用。
分層確定性密鑰創(chuàng)建 Hierarchical Deterministic Key Creation
早期的比特幣客戶端中錢包都是隨機(jī)生成的私鑰集合漓穿,這些密鑰都需要用戶自己保存副本嗤军,如果一旦密鑰丟失,那么對(duì)應(yīng)的錢包就不能訪問晃危,錢包控制的比特幣也就無法使用了叙赚。比特幣有一個(gè)避免地址重復(fù)使用的原則,每個(gè)比特幣地址只能一次交易僚饭,這樣用戶就會(huì)有大量的私鑰要進(jìn)行保存和備份震叮,所以早期方案不是一個(gè)好的辦法。
分層確定性密鑰和傳輸協(xié)議大大簡(jiǎn)化了錢包備份鳍鸵,消除了使用同一個(gè)錢包的多個(gè)程序之間重復(fù)通信的需要苇瓣,允許創(chuàng)建可以獨(dú)立操作的子賬戶,賦予每個(gè)父賬戶監(jiān)控或者控制其子賬戶的能力偿乖,即使子賬戶受到破壞击罪,每個(gè)賬戶分為完全訪問和限制訪問兩部分,這樣不受信任的用戶就或者程序就可以接收或者監(jiān)控支付贪薪,但是不能對(duì)外支付媳禁。
HD協(xié)議利用了ECDSA公鑰創(chuàng)建函數(shù)-point(),它去一個(gè)大數(shù)(私鑰)画切,并將其轉(zhuǎn)換為曲線上的的點(diǎn)(公鑰):
point(private_key) == public_key
因?yàn)?strong>point()的工作方式竣稽,它讓通過組合一個(gè)已經(jīng)存在的公鑰(父公鑰)和另一個(gè)公鑰(通過一個(gè)integer(i)值)來創(chuàng)建子公鑰成為可能。p是一個(gè)所有比特幣軟件都使用的全局常量。
point( (parent_private_key + i) % p ) == parent_public_key + point(i)
這就意味著兩個(gè)或者多個(gè)獨(dú)立的程序丧枪,如果對(duì)一個(gè)整數(shù)序列達(dá)成一致,就可以從單一的父密鑰對(duì)創(chuàng)建一系列唯一的子密鑰對(duì)庞萍,而不需要進(jìn)行額外的通信拧烦。此外,為收款分發(fā)新的公鑰钝计,程序可以在不接觸私鑰的情況實(shí)現(xiàn)恋博,從而允許公鑰分發(fā)程序在一個(gè)不安全的環(huán)境(web服務(wù)器)上運(yùn)行。
子公鑰也可以通過重復(fù)子密鑰分散操作來創(chuàng)建他們自己的子公鑰(孫公鑰):
point( (child_private_key + i) % p ) == child_public_key + point(i)
是否創(chuàng)建子公鑰或者更后代的公鑰私恬,對(duì)于所有交易來說债沮,使用一個(gè)可預(yù)測(cè)的整數(shù)序列不會(huì)比使用單一公鑰好,因?yàn)槿魏稳酥酪粋€(gè)子公鑰可以找到所有其他的通過這個(gè)父公鑰分散的子公鑰本鸣。相反的疫衩,使用一個(gè)隨機(jī)種子來確定生成的整數(shù)序列,這樣沒有種子的人無法看到子公鑰之間的關(guān)系荣德。
HD協(xié)議使用一個(gè)單一的根種子和無關(guān)聯(lián)的確定代際(unlinkable deterministically-generated)的整數(shù)來創(chuàng)建子代闷煤,孫子代和其他更后代的密鑰。每個(gè)子密鑰也通過它的父代獲得一個(gè)代際(deterministically-generated)種子涮瞻,稱為鏈代碼(chain code)鲤拿,所以一個(gè)chain code受到破壞,不會(huì)破壞整個(gè)序列的層次結(jié)構(gòu)署咽。
HD密鑰分散需要四個(gè)輸入:
- 父私鑰和父公鑰近顷,常規(guī)的未壓縮256 bits的ECDSA密鑰;
- 父chain code是256 bits看起來隨機(jī)的數(shù)據(jù)宁否;
- 索引index是程序指定的32-bit整數(shù)窒升。
在上圖所示的標(biāo)準(zhǔn)形式中,父chain code家淤、父公鑰和索引index被輸入到單向哈希HMAC-SHA512中异剥,生成確定代際但是看起來隨機(jī)(determistically-generated-but-seemingly-random)的512 bits數(shù)據(jù)。哈希輸出總共512 bits絮重,右邊的256 bits(低256 bits)數(shù)據(jù)被用來作為新的子chain code冤寿。哈希輸出的左邊256 bits被當(dāng)作一個(gè)整數(shù)和父私鑰或者父公鑰組合(父私鑰和哈希輸出的高256bits橢圓曲線上做加法模G運(yùn)算),來創(chuàng)建子私鑰或者子公鑰:
child_private_key == (parent_private_key + lefthand_hash_output) % G
child_public_key == point( (parent_private_key + lefthand_hash_output) % G )
child_public_key == point(child_private_key) == parent_public_key + point(lefthand_hash_output)
父chain code青伤、父公鑰督怜、索引index計(jì)算HMAC-SHA512的過程如下:父公鑰(256bits)和子密鑰的index(32bits)進(jìn)行拼接,公鑰在高位索引在地位狠角,合并后的字節(jié)序是大端号杠,對(duì)合并后的數(shù)據(jù)進(jìn)行HMAC-SHA512運(yùn)算,父chain code作為哈希密鑰。
可以看出來姨蟋,父私鑰和對(duì)應(yīng)代際的chain code可以算出子私鑰屉凯,然后用point()和子私鑰可以算出子公鑰,還可以用子公鑰和point(父chain code)算出子公鑰眼溶,這樣也可以在不需要私鑰的情況下悠砚,只知道某一代際的公鑰和對(duì)應(yīng)代際的chain code就可以算出下一代的公鑰。
指定不同的代際索引index堂飞,可以使用相同的父密鑰分散出不同的無關(guān)聯(lián)的子密鑰灌旧。子密鑰使用子chain code重復(fù)密鑰分散過程可以生成無關(guān)聯(lián)的孫密鑰。
因?yàn)閯?chuàng)建子密鑰需要密鑰和chain code兩者绰筛,密鑰和chain code合在一起被稱作擴(kuò)展密鑰枢泰。一個(gè)擴(kuò)展私鑰和對(duì)應(yīng)的擴(kuò)展公鑰具有相同的chain code。 主私鑰(最頂層)和主chain code是由隨機(jī)數(shù)生成铝噩。
根種子(root seed)是由123 bits衡蚂、256 bits或者512 bits的隨機(jī)數(shù)生成的。這個(gè)根種子薄榛,最少128 bits是需要用戶備份的唯一數(shù)據(jù)讳窟,將來用于通過特定的錢包和設(shè)置來分散所有的密鑰。
根種子通過哈希來創(chuàng)建512 bits看起來隨機(jī)的數(shù)據(jù)敞恋,通過這些數(shù)據(jù)來創(chuàng)建主私鑰和主chain code(合在一起稱作主擴(kuò)展密鑰)丽啡。主公鑰通過主私鑰使用point()計(jì)算得出,主公鑰和主chain code合在一起稱作主擴(kuò)展公鑰硬猫。主擴(kuò)展密鑰和其他擴(kuò)展密鑰在功能上等效补箍,只是因?yàn)樗挥谧钌蠈拥奈恢茫圆棚@得不同啸蜜。
根種子的哈希后512 bits的輸出坑雅,左邊256 bits作為主私鑰,右邊256bits作為主chain code
強(qiáng)化密鑰 Hardened Keys
強(qiáng)化擴(kuò)展密鑰(Hardened extended keys)修復(fù)了普通擴(kuò)展密鑰的一個(gè)潛在問題衬横。如果攻擊者獲得了一個(gè)普通擴(kuò)展密鑰的父chain code和父公鑰裹粤,他就可以暴力獲得所有的通過這個(gè)chain code派生出來的chain code。如果攻擊者還獲得了一個(gè)子私鑰蜂林、孫子私鑰或者更下一代的私鑰遥诉,他就可以使用chain code生成這個(gè)私鑰后代所有的私鑰了。
更糟糕的是噪叙,攻擊者可以逆向(reverse)普通的子私鑰分散公式矮锈,只要從子私鑰中減去父chain code就可以恢復(fù)父私鑰,如上圖子代和父代所示睁蕾。這意味著一個(gè)攻擊者苞笨,只要獲得了一個(gè)擴(kuò)展公鑰和及其后代的任何私鑰债朵,就可以恢復(fù)出改公鑰的私鑰及其分散出的所有密鑰。
因?yàn)閿U(kuò)展公鑰中有對(duì)應(yīng)層級(jí)的chain code瀑凝,所以可以得到這個(gè)公鑰后代任意代際的公鑰序芦,所以只要獲得了這個(gè)公鑰后代的私鑰,就可以算到這個(gè)私鑰上一代的chain code粤咪,然后通過私鑰-chain code計(jì)算出上一代私鑰芝加,最后推算出這個(gè)公鑰和后代的所有密鑰。
上面的強(qiáng)化公示將索引index射窒、父chain code和父私鑰組合在一起用來創(chuàng)建產(chǎn)生子chain code和子私鑰的數(shù)據(jù)。這個(gè)公示讓在不知道父私鑰的情況下不能創(chuàng)建子公鑰将塑。換句話說脉顿,父擴(kuò)展公鑰不能創(chuàng)建強(qiáng)化子公鑰。
強(qiáng)化密鑰生成過程点寥,在父私鑰前面補(bǔ)一個(gè)0x00字節(jié)艾疟,父私鑰和索引index拼接,私鑰在高位敢辩,索引在低位蔽莱,字節(jié)序?yàn)榇蠖恕?duì)拼接后的數(shù)據(jù)進(jìn)行HMAC-SHA512運(yùn)算戚长,哈希密鑰是父chain code盗冷,父私鑰和哈希的高256 bits做橢圓曲線上的加法模運(yùn)算生成子私鑰,低256 bits是子chain code同廉。如果ECC模運(yùn)算結(jié)果出現(xiàn)0仪糖,那么索引值遞增,然后再次計(jì)算密鑰迫肖。子公鑰可以通過子私鑰計(jì)算出來锅劝。
因此,強(qiáng)化擴(kuò)展私鑰沒有普通的擴(kuò)展私鑰有用蟆湖,然而強(qiáng)化擴(kuò)展私鑰會(huì)創(chuàng)建一個(gè)防火墻故爵,使得多層密鑰分散泄露不會(huì)發(fā)生。因?yàn)閺?qiáng)化子擴(kuò)展公鑰無法僅僅靠自己生成孫chain code隅津,父擴(kuò)展公鑰的泄露不能和孫私鑰的泄露組合創(chuàng)建重孫擴(kuò)展私鑰诬垂。
HD協(xié)議使用不同的索引index來指示是生成普通還是強(qiáng)化密鑰。索引Index從0x000x7FFFFFFF將生成普通密鑰饥瓷;索引Index從0x800000000xFFFFFFFF將生成強(qiáng)化密鑰剥纷。為了便于描述,許多開發(fā)者使用'(prime symbol)來表示強(qiáng)化密鑰呢铆,所以第一個(gè)普通密鑰(0x00)是0晦鞋,第一個(gè)強(qiáng)化密鑰(0x80000000)是0'。
(比特幣的開發(fā)者通常使用ASCII的撇號(hào),而不是使用unicode的prime symbol悠垛。)
這個(gè)壓縮描述進(jìn)一步結(jié)合斜杠和m或者M(jìn)前綴线定,指示層次(hierarchy)和密鑰類型。m表示私鑰确买,M表示公鑰斤讥。例如,m/0'/0/122'表示主私鑰的第1代(index=0)強(qiáng)化子密鑰的第1代(index=0)普通子密鑰的第123代(index=122)強(qiáng)化子私鑰(通過索引index)湾趾。
遵守BIP32 HD協(xié)議的錢包只創(chuàng)建主私鑰(m)的強(qiáng)化子密鑰來防止子密鑰泄露而導(dǎo)致主密鑰泄露芭商。因?yàn)橹髅荑€不存在普通子密鑰,所以主公鑰也不會(huì)在HD錢包里使用搀缠。所有其他密鑰可以有普通子密鑰铛楣,所以可以使用對(duì)應(yīng)的普通擴(kuò)展公鑰。
HD協(xié)議還描述了擴(kuò)展公鑰和擴(kuò)展私鑰的序列化格式艺普。詳細(xì)情況可以參看BIP32協(xié)議簸州。
保存根種子 Storing Root Seeds
HD協(xié)議里的根種子(root seeds)是128、256或者512 bits的隨機(jī)數(shù)歧譬,這些種子需要備份保存岸浑。為了方便,可以使用非數(shù)字化備份的方法瑰步,比如記憶矢洲、手抄等。BIP39定義了一個(gè)方法缩焦,通過助記符來創(chuàng)建512 bits的根種子兵钮。
生成單詞數(shù)與使用的熵值相關(guān):
Entropy Bits | Words |
---|---|
128 | 12 |
160 | 15 |
192 | 18 |
224 | 21 |
256 | 24 |
密碼短語(passphrase)可以是任意長(zhǎng)度,它可以簡(jiǎn)單得追加到助記符pseudo-sentence舌界,mnemonic和password將使用2048次HMAC-SHA512運(yùn)算掘譬,產(chǎn)生一個(gè)看起來隨機(jī)的512 bits種子。
松散密鑰錢包 Loose-Key Wallets
松散密鑰錢包似乎中文也有叫零型非確定錢包呻拌,也被稱作Just a Bunch Of Keys(JBOK)葱轩,是一種Bitcoin Core客戶端早期的錢包形式,已經(jīng)被棄用藐握。Bitcoin Core客戶端錢包通過偽隨機(jī)數(shù)發(fā)生器自動(dòng)創(chuàng)建100個(gè)公私鑰對(duì)供以后使用靴拱。
這些沒有使用的私鑰存儲(chǔ)在一個(gè)虛擬的密鑰池(key pool)中,之前生成的密鑰被使用后猾普,就會(huì)生成新的密鑰放到池中袜炕,保證池中有100個(gè)未使用的密鑰。