皮夹
“钱包”一词用于描述比特币中的一些不同事物。
总体而言,钱包是一种充当主要用户界面的应用程序。钱包控制着对用户资金的访问,管理密钥和地址,跟踪余额以及创建和签署交易。
从程序员的角度来看,更狭义地讲,“钱包”一词是指用于存储和管理用户密钥的数据结构。
在本章中,我们将探讨第二种含义,其中钱包是私钥的容器,通常以结构化文件或简单数据库的形式实现。
钱包技术概述
在本节中,我们总结了用于构建用户友好,安全和灵活的比特币钱包的各种技术。
关于比特币的一个常见误解是,比特币钱包中包含比特币。
实际上,钱包只包含钥匙。 “硬币”记录在比特币网络的区块链中。
用户通过使用钱包中的密钥签署交易来控制网络上的硬币。从某种意义上说,比特币钱包是钥匙串。
- 提示
比特币钱包包含钥匙,而不是硬币。
每个用户都有一个包含钥匙的钱包。
钱包实际上是包含一对私钥/公钥的钥匙串(请参阅[private_public_keys])。
用户使用密钥在交易上签名,从而证明他们拥有交易输出(他们的硬币)。
代币以交易输出的形式(通常称为vout或txout)存储在区块链上。
类型
钱包有两种主要类型,通过它们包含的密钥是否相互关联来区分。
第一种类型是不确定的钱包,其中每个密钥都是根据随机数独立生成的。按键彼此不相关。这种钱包在短语“ Just a Bunch Of Keys”中也称为JBOK钱包。
第二种钱包是确定性钱包,其中所有密钥均来自单个主密钥(称为种子)。这种钱包中的所有密钥都是相互关联的,如果密钥具有原始种子,则可以再次生成。确定性钱包中使用了许多不同的密钥派生方法。最常用的推导方法使用树状结构,被称为分层确定性或HD钱包。
确定性钱包从随机序列(熵)初始化。为了使它们更易于使用,随机序列被编码为英语单词,也称为助记符代码单词。
接下来的几节将对这些技术中的每一个进行高级别的介绍。
非确定性(随机)钱包
在第一个比特币钱包(现在称为Bitcoin Core)中,钱包是随机生成的私钥的集合。
例如,原始的Bitcoin Core客户端在首次启动时会预先生成100个随机私钥,并根据需要生成更多密钥,每个密钥仅使用一次。
此类钱包已被确定性钱包所取代,因为它们麻烦于管理,备份和导入。
随机密钥的缺点是,如果生成许多密钥,则必须保留所有密钥的副本,这意味着必须经常备份钱包。必须备份每个密钥,否则如果无法访问钱包,则其控制的资金将不可避免地丢失。
通过仅将每个比特币地址用于一个事务,这与避免地址重用的原理直接冲突。地址重用通过将多个事务和地址相互关联来减少隐私。
Type-0非确定性钱包是一个较差的钱包选择,特别是在您要避免地址重用的情况下,尤其是因为它意味着管理许多密钥,因此需要频繁备份。
尽管Bitcoin Core客户端包括一个0型钱包,但Bitcoin Core的开发人员不建议使用此钱包。
Type-0非确定性(随机)钱包:随机生成的密钥的集合显示了一个不确定性的钱包,其中包含一个松散的随机密钥集合。
- TIP
除简单测试外,不建议使用不确定性钱包。
它们太麻烦了,无法备份和使用。
取而代之的是,使用具有助记符随机序列(熵或“初始种子”)的基于行业标准的HD钱包进行备份。
- Figure 1. Type-0 nondeterministic (random) wallet: a collection of randomly generated keys
确定性(种子)钱包
确定性或“种子”钱包是包含私钥的钱包,这些私钥都是通过使用单向哈希函数从一个共同的种子派生而来的。
种子是一个随机生成的数字,它与其他数据(例如索引号或“链码”)组合(请参阅HD钱包(BIP-32 / BIP-44)),以导出私钥。
在确定性钱包中,种子足以恢复所有派生的密钥,因此在创建时进行一次备份就足够了。
种子也足以用于钱包的导出或导入,从而允许在不同的钱包实现之间轻松迁移所有用户的密钥。
Type-1确定性(种子)钱包:从种子派生的确定性密钥序列显示了确定性钱包的逻辑图。
- Figure 2. Type-1 deterministic (seeded) wallet: a deterministic sequence of keys derived from a seed
高清钱包(BIP-32 / BIP-44)
确定性钱包的开发使从一个“种子”中轻松获得许多密钥成为可能。
确定性钱包的最先进形式是由BIP-32标准定义的HD钱包。
HD钱包包含以树结构派生的密钥,以便父密钥可以派生一系列子密钥,每个子密钥都可以派生一系列孙子密钥,依此类推,直至无限深度。
这种树形结构在Type-2 HD钱包中进行了说明:从单个种子生成的密钥树。
- Figure 3. Type-2 HD wallet: a tree of keys generated from a single seed
与随机(不确定)密钥相比,HD钱包具有两个主要优势。
首先,树形结构可用于表达其他组织含义,例如,当特定的子键分支用于接收传入的付款,而另一个分支用于接收来自传出付款的更改时。
键的分支也可以在公司设置中使用,将不同的分支分配给部门,子公司,特定功能或会计类别。
HD钱包的第二个优点是用户可以创建一系列公共密钥,而无需访问相应的私有密钥。
这样一来,HD钱包就可以在不安全的服务器上使用,也可以仅用于接收功能,从而为每笔交易发布不同的公钥。
公用密钥不需要预先加载或派生,但是服务器没有可以花费资金的专用密钥。
种子和记忆代码(BIP-39)
HD钱包是一种用于管理许多密钥和地址的非常强大的机制。 如果将它们与标准化的方法结合使用,它们将更加有用,该标准化的方法可以通过一系列易于转录,导出和导入各个钱包的英语单词来创建种子。
这称为助记符,标准由BIP-39定义。
如今,大多数比特币钱包(以及其他加密货币的钱包)都使用此标准,并且可以使用可互操作的助记符来导入和导出种子以进行备份和恢复。
让我们从实际的角度来看这件事。
下列哪个种子更容易转录,记录在纸上,无错误阅读,导出并导入另一个钱包?
- 确定性钱包的种子(十六进制)
0C1E24E5917779D297E14D45F14E1A1A
- 确定性钱包的种子,来自12个单词的助记符
army van defense carry jealous true
garbage claim echo media make crunch
钱包最佳做法
随着比特币钱包技术的成熟,出现了一些通用的行业标准,这些标准使比特币钱包具有广泛的互操作性,易用性,安全性和灵活性。
这些通用标准是:
-
助记码字,基于BIP-39
-
基于BIP-32的高清钱包
-
基于BIP-43的多功能HD钱包结构
-
基于BIP-44的多币种和多账户钱包
这些标准可能会更改,或者可能因将来的发展而过时,但现在它们形成了一组互锁技术,这些技术已成为事实上的比特币钱包标准。
这些标准已被广泛的软件和硬件比特币钱包采用,从而使所有这些钱包都可以互操作。用户可以导出在这些钱包之一中生成的助记符,然后将其导入另一个钱包中,以恢复所有交易,密钥和地址。
支持这些标准的软件钱包的一些示例包括(按字母顺序列出)Bluewallet,Breadwallet,Copay和Multibit HD。支持这些标准的硬件钱包的示例包括(按字母顺序列出)KeepKey,Ledger和Trezor。
以下各节详细研究了每种技术。
如果您要实施的是比特币钱包,则应将其构建为HD钱包,并遵循BIP-32,BIP-39,BIP-43和BIP- 44个标准,如以下各节所述。
使用比特币钱包
在[用户故事]中,我们介绍了里约热内卢一个富有进取心的青少年Gabriel,他经营着一家简单的网上商店,出售出售比特币品牌的T恤,咖啡杯和贴纸。
Gabriel使用Trezor比特币硬件钱包(Trezor设备:硬件中的比特币高清钱包)来安全地管理他的比特币。
Trezor是一个简单的USB设备,带有两个按钮,用于存储密钥(以HD钱包的形式)并签署交易。
Trezor钱包实现了本章中讨论的所有行业标准,因此Gabriel并不依赖于任何专有技术或单一供应商解决方案。
当Gabriel首次使用Trezor时,设备会生成一个随机序列(熵),相关的助记符,并从内置的硬件随机数生成器中获取种子。
在此初始化阶段,钱包在屏幕上逐个显示了一个编号的单词序列(请参阅Trezor显示助记词之一)。
通过记下该助记符,Gabriel创建了一个备份(请参阅Gabriel的助记符纸质备份),该备份可用于在Trezor设备丢失或损坏的情况下进行恢复。
此助记符可用于在新的Trezor或许多兼容的软件或硬件钱包中的任何一个中进行恢复。
请注意,单词的顺序很重要,因此助记符纸的备份中每个单词都有编号的空格。
加百列必须仔细记录编号空间中的每个单词,以保持正确的顺序。
1.army 7.garbage
2.van 8.claim
3.defense 9.echo
4.carry 10.media
5.jealous 11.make
6.true 12.crunch
为简单起见,在加百列的助记符纸质备份中显示了12个单词的助记符。
实际上,大多数硬件钱包都会生成更安全的24字助记符。
助记符的使用方式完全相同,无论长度如何。
对于他的网上商店的第一个实现,Gabriel使用在Trezor设备上生成的单个比特币地址。
所有客户都使用该单一地址处理所有订单。
就像我们将看到的那样,这种方法有一些缺点,可以通过HD钱包加以改进。
钱包技术详细信息
现在,让我们详细研究许多比特币钱包使用的重要行业标准。
助记码字(BIP-39)
助记符代码字是代表(编码)用作种子以导出确定性钱包的随机数的字序列。
单词序列足以重新创建种子,并从那里重新创建钱包和所有派生密钥。
使用助记词实现确定性钱包的钱包应用程序将在首次创建钱包时向用户显示12到24个单词的序列。
单词序列是钱包备份,可用于恢复和重新创建同一或任何兼容钱包应用程序中的所有密钥。
助记词使用户更容易备份钱包,因为与随机数字序列相比,助记词易于阅读和正确转录。
助记词经常与“大脑钱包”相混淆。 她们不一样。
主要区别在于脑钱包由用户选择的单词组成,而助记词由钱包随机创建并呈现给用户。
这个重要的区别使助记词更加安全,因为人类是非常差的随机性来源。
助记符代码在BIP-39中定义(请参阅[appdxbitcoinimpproposals])。
请注意,BIP-39是助记码标准的一种实现。
Electrum钱包使用的标准和BIP-39之前的标准不同,使用的单词也有所不同。
BIP-39是公司在Trezor硬件钱包后面提出的,与Electrum的实现不兼容。
但是,BIP-39现在已经在数十种可互操作的实现中获得了广泛的行业支持,应被视为事实上的行业标准。
BIP-39定义了助记码和种子的创建,在此我们分九步进行描述。
为了清楚起见,该过程分为两部分:生成助记词显示步骤1至6,从助记词到种子显示步骤7至9。
生成助记词
钱包使用BIP-39中定义的标准化流程自动生成助记词。 钱包从熵源开始,添加校验和,然后将熵映射到单词列表:
-
创建一个128到256位的随机序列(熵)。
-
通过获取其SHA256哈希的第一(熵长度/ 32)位来创建随机序列的校验和。
-
将校验和添加到随机序列的末尾。
-
将结果分成11位长度的段。
-
将每个11位值映射到2048个单词的预定义词典中的一个单词。
-
助记码是单词序列。
生成熵并将其编码为助记词显示了如何使用熵来生成助记词。
- Figure 6. Generating entropy and encoding as mnemonic words
助记符代码:熵和单词长度表示熵数据的大小与单词中助记符代码的长度之间的关系。
- 表2.助记码:熵和字长
Entropy (bits) | Checksum (bits) | Entropy + checksum (bits) | Mnemonic length (words) |
---|---|---|---|
128 | 4 | 132 | 12 |
160 | 5 | 165 | 15 |
192 | 6 | 198 | 18 |
224 | 7 | 231 | 21 |
256 | 8 | 268 | 24 |
从助记符到种子
助记词表示长度为128到256位的熵。然后,通过使用键拉伸函数PBKDF2,使用熵来导出更长的(512位)种子。然后将产生的种子用于构建确定性钱包并导出其密钥。
密钥拉伸功能采用两个参数:助记符和盐。在键拉伸功能中加盐的目的是使构建难以进行暴力攻击的查找表变得困难。
在BIP-39标准中,该盐还有另一个目的-它允许引入密码短语,该密码短语是保护种子的附加安全因素,正如我们将在BIP-39的“可选密码短语”中更详细地描述的那样。
步骤7至9中描述的过程是前面生成助记词中描述的过程的继续:
-
PBKDF2密钥拉伸功能的第一个参数是步骤6中产生的助记符。
-
PBKDF2密钥拉伸功能的第二个参数是salt。该salt由字符串常量“助记符”和一个可选的用户提供的密码短语字符串组成。
-
PBKDF2使用HMAC-SHA512算法使用2048轮散列来扩展助记符和salt参数,从而产生512位值作为其最终输出。那个512位的值就是种子。
从助记符到种子显示了助记符如何用于生成种子。
- Figure 7. From mnemonic to seed
- TIPS
带有2048轮散列的密钥拉伸功能是一种非常有效的保护措施,可防止对助记符或密码短语的暴力攻击。
尝试数以千计的密码短语和助记符组合非常昂贵(在计算中),而可能派生的种子数量很多(2^512)。
BIP-39中的可选密码
BIP-39标准允许在衍生种子时使用可选的密码短语。
如果不使用密码短语,则将助记符与由常量字符串“助记符”组成的盐扩展,从任何给定的助记符生成特定的512位种子。
如果使用密码短语,则拉伸功能会产生与该助记符不同的种子。
实际上,在给定单个助记符的情况下,每种可能的密码短语都会导致不同的种子。
本质上,没有“错误的”密码短语。 所有密码短语都是有效的,并且它们都导致不同的种子,从而形成大量可能的未初始化的钱包。
可能的钱包如此之大(2^512),以至于几乎没有强行使用暴力或意外猜测正在使用的钱包的可能性。
可选密码短语具有两个重要功能:
(1)第二个因素(记住的东西)使助记符本身无用,可以保护助记符备份免受小偷的侵害。
(2)一种合理的可否定性或“胁迫钱包”形式,其中选定的密码短语会导致一个钱包,其中包含少量资金,这些资金用于将攻击者从包含大部分资金的“真实”钱包中转移出来。
但是,重要的是要注意,使用密码短语还会带来丢失的风险:
(1)如果钱包所有者无能为力或死了,并且没人知道密码,则助记符代码将无用,并且存储在钱包中的所有资金将永远丢失。
(2)相反,如果所有者在与助记符代码相同的位置备份密码短语,则会破坏第二个因素的目的。
尽管密码短语非常有用,但考虑到所有者可以生存并允许其家人收回加密货币资产的可能性,它们仅应与精心计划的备份和恢复过程结合使用。
使用助记符代码
BIP-39被实现为许多不同编程语言的库:
由SatoshiLabs团队提出的标准BIP-39的标准参考实现,使用Python
BIP-39的实现,作为流行的bitcoinJS框架的一部分,采用JavaScript
BIP-39的实现,是流行的Libbitcoin框架的一部分,采用 C++
从种子创建高清钱包
HD钱包是从单个根种子创建的,该种子是128位,256位或512位随机数。
最常见的是,此种子是从上一节中详细说明的助记符生成的。
HD钱包中的每个密钥都是确定性地从该根种子派生的,这使得可以在任何兼容的HD钱包中从该种子重新创建整个HD钱包。
这样,仅传输根种子的助记符,就可以轻松备份,还原,导出和导入包含数千甚至数百万个密钥的HD钱包。
从根种子创建主密钥和链码中显示了为HD钱包创建主密钥和主链码的过程。
- Figure 8. Creating master keys and chain code from a root seed
根种子被输入到HMAC-SHA512算法中,所得的哈希值用于创建主私钥(m)和主链代码(c)。
然后,主私钥(m)使用我们在[pubkey]中看到的常规椭圆曲线乘法过程 m * G 生成相应的主公钥(M)。
链码(c)用于在从父键创建子键的函数中引入熵,这将在下一部分中看到。
私生子密钥派生
HD钱包使用子密钥派生(CKD)功能从父密钥派生子密钥。
子密钥派生函数基于单向哈希函数,该函数结合了以下内容:
-
父级私钥或公钥(ECDSA压缩密钥)
-
称为链码的种子(256位)
-
索引号(32位)
链码用于向过程中引入确定性随机数据,因此仅知道索引和子键不足以派生其他子键。除非您也具有链码,否则知道子密钥将无法找到其子级。初始链代码种子(位于树的根部)是从种子中获得的,而后续子链代码是从每个父链代码中得出的。
如下所述,将这三个项目(父键,链码和索引)组合并进行哈希处理以生成子键。
将父公钥,链码和索引号组合在一起,并使用HMAC-SHA512算法进行哈希处理以生成512位哈希。此512位哈希被分为两个256位一半。哈希输出的右半部分256位将成为子级的链码。哈希的左半部分256位被添加到父密钥,以产生子私有密钥。在扩展父级私钥以创建子级私钥中,我们看到了将索引设置为0以产生父级的“零”(按索引优先)子级的示例。
- Figure 9. Extending a parent private key to create a child private key
更改索引使我们可以扩展父级并按顺序创建其他子级,例如,Child 0,Child 1,Child 2等。
每个父键可以有2,147,483,647(231)个子级(2^31是整个2^32范围的一半) 可用,因为另一半保留给特殊类型的推导,我们将在本章后面讨论)。
在树的下一级重复此过程,每个子代可以无限次成为父代并创建自己的子代。
使用派生的子键
子私钥与不确定(随机)密钥没有区别。
由于派生函数是单向函数,因此不能使用子键来查找父键。
子键也不能用于查找任何同级。
如果您有第n个孩子,则找不到其同胞,例如n–1个孩子或n + 1个孩子,或该序列中的任何其他孩子。
只有父键和链码才能派生所有子代。 如果没有子链代码,则子密钥也不能用于派生任何子孙。
您需要子私钥和子链代码来启动新分支并派生孙子代。
那么子私钥可以单独用作什么呢?
它可以用来制作公钥和比特币地址。 然后,它可以用于签署交易,以花去支付给该地址的任何款项。
- TIPS
子私钥,相应的公钥和比特币地址都与随机创建的密钥和地址没有区别。
它们是序列的一部分的事实在创建它们的HD钱包功能之外是不可见的。
创建后,它们将完全像“普通”键一样操作。
扩展键
如前所述,密钥派生函数可用于基于以下三个输入在树的任何级别上创建子代:密钥,链码和所需子代的索引。密钥和链式代码是两个必不可少的要素,将它们组合在一起称为扩展密钥。术语“扩展密钥”也可以被认为是“可扩展密钥”,因为这样的密钥可用于派生子代。
扩展密钥被存储和表示为256位密钥和256位链码到512位序列中的连接。有两种类型的扩展键。扩展私钥是私钥和链码的组合,可用于派生子私钥(并从中获得子公钥)。扩展的公共密钥是公共密钥和链码,可用于创建子公共密钥(仅公共),如[public_key_derivation]中所述。
将扩展密钥视为HD钱包树形结构中分支的根。使用分支的根,可以派生分支的其余部分。扩展的私钥可以创建一个完整的分支,而扩展的公钥只能创建一个公钥的分支。
- TIPS
扩展密钥由私钥或公钥以及链码组成。
扩展键可以创建子代,从而在树结构中生成自己的分支。
共享扩展密钥可以访问整个分支。
扩展密钥使用Base58Check进行编码,可以轻松地在兼容BIP-32的不同钱包之间进行导出和导入。
扩展密钥的Base58Check编码使用特殊的版本号,当以Base58字符编码时,会导致前缀“ xprv”和“ xpub”,以使其易于识别。
因为扩展密钥是512或513位,所以它也比我们之前看到的其他Base58Check编码的字符串长得多。
这是在Base58Check中编码的扩展私钥的示例:
xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c
这是在Base58Check中编码的相应扩展公共密钥:
xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9
公子密钥派生
如前所述,HD钱包的一个非常有用的特性是能够从公共父密钥派生公共子密钥而无需私有密钥。这给了我们两种导出子公钥的方法:从子私钥或直接从父公钥导出。
因此,可以使用扩展的公共密钥来导出HD钱包结构的该分支中的所有公共密钥(仅公共密钥)。
此快捷方式可用于创建非常安全的公用密钥-仅在服务器或应用程序具有扩展公用密钥的副本而没有任何私人密钥的部署中。这种部署可以产生无限数量的公钥和比特币地址,但不能花费发送到这些地址的任何钱。同时,在另一台更安全的服务器上,扩展的私钥可以派生所有相应的私钥来签署交易并花钱。
该解决方案的一个常见应用是在为电子商务应用程序提供服务的Web服务器上安装扩展的公共密钥。
Web服务器可以使用公钥派生功能为每个交易(例如,为客户购物车)创建新的比特币地址。 Web服务器将没有任何容易被盗用的私钥。如果没有高清钱包,唯一的方法就是在单独的安全服务器上生成数千个比特币地址,然后将其预加载到电子商务服务器上。这种方法很麻烦,并且需要不断维护,以确保电子商务服务器不会“用完”地址。
该解决方案的另一个常见应用是用于冷库或硬件钱包。在那种情况下,扩展的私钥可以存储在纸钱包或硬件设备(例如Trezor硬件钱包)上,而扩展的公钥可以保持在线状态。用户可以随意创建“接收”地址,而私钥可以安全地脱机存储。为了花费资金,用户可以在脱机签名比特币客户端上使用扩展的私钥,或者在硬件钱包设备(例如Trezor)上签名交易。扩展父公共密钥以创建子公共密钥说明了扩展父公共密钥以派生子公共密钥的机制。
- Figure 10. Extending a parent public key to create a child public key
强化子密钥派生
从xpub派生公钥分支的功能非常有用,但存在潜在的风险。访问xpub不能访问子私钥。但是,由于xpub包含链码,因此,如果已知子私钥或以某种方式泄漏了子私钥,则可以将其与链码一起使用,以导出所有其他子私钥。
单个泄露的子私钥以及父链代码将揭示所有子级的所有私钥。更糟糕的是,子私钥与父链代码一起可用于推导父私钥。
为了应对这种风险,HD钱包使用了另一种派生功能,即硬化派生功能,该功能“打破”了父公钥和子链代码之间的关系。强化派生函数使用父私钥而不是父公钥来派生子链代码。这将在父/子序列中创建一个“防火墙”,并带有不能用于泄露父密钥或同级私有密钥的链代码。强化派生函数看起来与普通的子私钥派生几乎相同,除了将父私钥用作哈希函数的输入(而不是父公钥)之外,如子键的强化派生中的图所示;省略父公钥。
- Figure 11. Hardened derivation of a child key; omits the parent public key
当使用强化的私有派生函数时,所得子私有密钥和链码与正常派生函数所产生的完全不同。 生成的密钥“分支”可用于生成不易受攻击的扩展公共密钥,因为其中包含的链代码无法被利用来揭示任何私有密钥。
因此,在使用扩展公钥的级别之上的树中,使用了硬化派生来创建“间隙”。
简而言之,如果您想利用xpub的便利性来派生公钥的分支,而又不让自己暴露于链代码泄漏的风险中,则应该从强化的父密钥而不是普通的(非- 强化)父键。
最佳做法是,主密钥的1级子代始终通过强化派生而派生,以防止损害主密钥。
正常和硬化派生的索引号
推导函数中使用的索引号是32位整数。
为了轻松地区分通过正常派生函数派生的密钥和通过强化派生派生的密钥,此索引号分为两个范围。
0到231–1之间的索引号(0x0到0x7FFFFFFF)仅用于常规推导。索引号介于231和232–1之间(0x80000000到0xFFFFFFFF)仅用于强化派生。
因此,如果索引号小于2^31,则该子项是正常的;而如果索引号等于或大于2^31,则该子项将被硬化。
为了使索引号更易于阅读和显示,已硬化的孩子的索引号从零开始显示,但带有撇号。
因此,第一个普通子项显示为0,而第一个强化子项(索引为0x80000000)显示为 0'
。
然后,按顺序,第二个强化密钥的索引为0x80000001,并显示为 1'
,依此类推。
当您看到高清钱包索引 1'
时,表示2^31 + i。
HD钱包密钥标识符(路径)
HD钱包中的密钥使用“路径”命名约定标识,树的每个级别均由斜杠(/)字符分隔(请参阅HD钱包路径示例)。
从主私钥派生的私钥以“m”开头。 从主公用密钥派生的公用密钥以“ M”开头。
因此,主私钥的第一个子私钥为m/0。 第一个子公钥为M/0。 第一个孩子的第二个孙子是m/0/1,依此类推。
从右到左读取密钥的“祖先”,直到到达派生密钥的主密钥为止。
例如,标识符m/x/y/z描述了作为父私钥 m/x/y 的第z个子代的私钥,这是父私钥 m/x 的第y个子代, 是父主私钥m的第x个子代。
浏览HD钱包树结构
HD钱包树结构提供了极大的灵活性。每个父母扩展密钥可以拥有40亿个孩子:20亿正常孩子和20亿硬化孩子。这些孩子中的每个孩子都可以再有40亿个孩子,依此类推。这棵树可以无限长地随你想要的深。但是,由于具有所有的灵活性,导航这棵无限树变得非常困难。在不同的实现之间转移HD钱包特别困难,因为内部组织进入分支机构和分支机构的可能性是无限的。
通过为HD钱包树的结构创建一些建议的标准,两个BIP提供了解决此复杂性的方法。
BIP-43建议使用第一个强化的子索引作为特殊标识符,以表示树结构的“用途”。基于BIP-43,HD钱包应仅使用树的一个1级分支,并且索引号通过定义树的用途来标识树的其余部分的结构和名称空间。
例如,仅使用分支 m/i 的HD钱包旨在表示特定目的,并且该目的由索引号“ i”标识。
为了扩展该规范,BIP-44提出了一种多帐户结构,作为BIP-43下的“目的”编号44’。遵循BIP-44结构的所有HD钱包的标识是,它们仅使用树的一个分支:m / 44’/。
BIP-44将结构指定为由五个预定义的树级别组成:
m / purpose' / coin_type' / account' / change / address_index
一级“目的”始终设置为44’。第二层“ coin_type”指定了加密货币硬币的类型,允许使用多货币HD钱包,其中每种货币在第二层之下都有其自己的子树。
目前定义了三种货币:比特币是m / 44’/ 0’,比特币测试网是m / 44' / 1&#x27 ;,莱特币是m / 44' / 2'。
树的第三层是“帐户”,它允许用户出于会计或组织目的将其钱包细分为单独的逻辑子帐户。
例如,一个高清钱包可能包含两个比特币“帐户”:m / 44' / 0' / 0'和m / 44' / 0' / 1'。每个帐户都是其自己的子树的根。
在第四级“更改”上,HD钱包具有两个子树,一个用于创建接收地址,另一个用于创建更改地址。
请注意,尽管先前的级别使用硬化推导,但此级别使用正态推导。这是为了允许树的该级别导出扩展的公共密钥,以在不安全的环境中使用。
HD钱包将可用地址作为第四级的子级派生,使树的第五级成为“ address_index”。
例如,主帐户中用于比特币支付的第三个接收地址将是M / 44' / 0' / 0' / 0/2。
在Web Store上使用扩展公钥
通过在Gabriel的网上商店中继续我们的故事,让我们看看如何使用高清钱包。
加布里埃尔(Gabriel)首先根据一个简单的托管Wordpress页面建立了自己的网上商店,作为一种爱好。他的商店非常基础,只有几页,只有一张带有单个比特币地址的订单。
加布里埃尔将其Trezor设备生成的第一个比特币地址用作其商店的主要比特币地址。这样,所有收款都将被支付到他的Trezor硬件钱包控制的地址。
客户可以使用该表格提交订单,然后将付款发送到加百列的已发布比特币地址,从而触发一封包含订单详细信息的电子邮件,供加百列处理。每周只有几个订单,此系统运行良好。
但是,这家小型网络商店非常成功,并吸引了当地社区的许多订单。很快,加百列不知所措。由于所有订单都支付相同的地址,因此很难正确匹配订单和交易,尤其是当多个相同金额的订单并排出现时。
加百利(Gabriel)的高清钱包提供了一种更好的解决方案,因为它无需知道私钥就可以导出公钥。加布里埃尔(Gabriel)可以在其网站上加载扩展的公共密钥(xpub),该密钥可用于为每个客户订单获取唯一的地址。加布里埃尔(Gabriel)可以用Trezor的资金来花钱,但是网站上加载的xpub只能生成地址并接收资金。 HD钱包的此功能是一项强大的安全功能。加百利的网站不包含任何私钥,因此不需要高度的安全性。
为了导出xpub,Gabriel将基于Web的软件与Trezor硬件钱包配合使用。必须插入Trezor设备才能导出公共密钥。请注意,硬件钱包永远不会导出私钥,这些私钥始终保留在设备上。从Trezor硬件钱包中导出xpub将显示Gabriel用于导出xpub的Web界面。
帐户发现和管理
加百列的生意蒸蒸日上。他已向BTCPay Server提供了扩展的公共密钥(xpub),该服务器正在为他的网站的客户生成唯一的地址。每当Gabriel网站上的客户点击具有指定付款方式(在本例中为比特币)的“结帐”按钮时,BTCPay Server就会为该客户生成一个新地址。更具体地说,BTCPay Server会在address_index树上进行迭代,以创建一个新的地址以显示给客户,这是由BIP-44定义的。如果客户决定转换付款方式或完全放弃交易,则该比特币地址将不被使用,并且不会立即被其他客户使用。
加布里埃尔(Gabriel)的网站可能很快会为购物客户提供大量出色的地址,其中一些地址可能未被使用并最终失效。一旦这些地址过期,BTCPay Server将返回以重复使用这些地址以填补address_index中的空白,但是很清楚,金钱实际所在的分层确定性树的address_index叶子之间如何可能存在空白。
假设Gabriel有兴趣查看他在仅与BTCPay Server分开但也符合BIP-44标准的仅手表钱包(可以查看交易历史记录,但不花费资金的钱包)上赚取的比特币总量。
这个单独的钱包应该如何在这棵巨大的等级制树中寻找资金,什么时候应该停止寻找呢?大多数钱包通常会遵循利用间隔限制(一个预先定义的限制)的迭代过程,如果连续超过此限制编号没有使用的地址,则钱包将停止搜索地址链。默认的间隙限制通常设置为20。这在BIP-44中有详细说明。
- TIPS
差距限制解释了一种现象,在这种现象下,钱包的进口可能显示不正确或零余额。
资金没有丢失,而是钱包导入功能没有遍历足够的叶子来完全检测到资金。
许多钱包允许更改此默认缺口限额,Gabriel可能需要增加此限额,以允许其钱包完全导入他的交易历史记录。
参考资料
https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc