Mastering Bitcoin Chapter05 钱包

5.1 钱包技术概述

比特币钱包中只有钥匙,没有比特币。“钱币”被记录在比特币网络的区块链中。有两种主要类型的钱包,区别在于它们包含的多个密钥是否相互关联。

  • 非确定性钱包(nondeterministic wallet),其中每个密钥都是从随机数独立生成的。密钥彼此无关。这种钱包也被称为“Just a Bunch Of Keys(一堆密钥)”,简称JBOK钱包。

  • 确定性钱包(deterministic wallet),所有的密钥都是从一个主密钥派生出来,这个主密钥即为种子(seed)。该类型钱包中所有密钥都相互关联,如果有原始种子,则可以再次生成全部密钥。确定性钱包中使用了许多不同的密钥推导方法。最常用的推导方法是使用树状结构,称为分级确定性钱包或 HD 钱包。 ### 5.1.1 非确定性(随机)钱包

随机密钥的缺点就是如果你生成很多私钥,你必须保存它们所有的副本。这就意味着这个钱包必须被经常性 地备份。每一个密钥都必须备份。其含有的随机密钥是个松散的集合。

5.1.2 确定型(种子)钱包

“种子”钱包包含通过使用单项离散函数而可从公共的种子生成的私钥。种子是随机生成的数字。在确定性钱包中,种子足够恢复所有的已经产生的私钥,所以只用在初始创建时的一个简单备份就足以搞定。并且种子也足够让钱包导入或者导出。

5.1.3 分层确定性钱包(HD Wallets (BIP-32/BIP-44))

确定性钱包被开发成更容易从单个“种子”中生成许多密钥。确定性钱包的最高级形式是通过BIP0032 标准定义的 HD 钱包。HD 钱包包含以树状结构衍生的密钥,使得父密钥可以衍生一系列子密钥,每个子密钥可以衍生出一系列孙密钥,以此类推,无限衍生。图5-3展示了树状结构。

相比较随机(不确定性)密钥,HD钱包有两个主要的优势。

  1. 树状结构可以被用来表达额外的组织含义。比如当一个特定分支的子密钥被用来接收交易收入并且有另一个分支的子密钥用来负责支付花费。

  2. 用户可以创建一系列公钥,而不需要访问对应的私钥。这样,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

5.1.6 使用比特币钱包

略。

5.2 钱包技术细节

5.2.1 助记码词汇(BIP-39)

助记码词汇是英文单词序列代表(编码)用作种子对应所确定性钱包的随机数。

在首次创建钱包时,带有助记码的,运行确定性钱包的钱包的应用程序将会向使用者展示一个 12至 24 个词的顺序。单词的顺序就是钱包的备份。它也可以被用来恢复以及重新创造应用程序相同或者兼容的钱包的密钥。

BIP-39 定义了助记符码和种子的创建,我们在这里描述了九个步骤。 为了清楚起见,该过程分为两部分:1-6 步是创建助记词,7-9 步是从助记词到种子。

5.2.2 创建助记词

助记词是由钱包使用 BIP-39 中定义的标准化过程自动生成的。 钱包从熵源开始,增加校验和,然后将熵映射到单词列表:

  1. 创建一个128 到 256 位的随机序列(熵)。

  2. 提出 SHA256 哈希前几位(熵长/ 32),就可以创造一个随机序列的校验和。

  3. 将校验和添加到随机序列的末尾。

  4. 将序列划分为包含 11 位的不同部分。

  5. 将每个包含 11 位部分的值与一个已经预先定义 2048 个单词的字典做对应。

  6. 生成的有顺序的单词组就是助记码

熵数据的大小和助记词的长度之间的关系:

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 264 24

5.2.3 从助记词生成种子

助记词表示长度为 128 至 256 位的熵。 通过使用密钥延伸函数 PBKDF2,熵被用于导出较长的(512位)种子。将所得的种子用于构建确定性钱包并得到其密钥。

密钥延伸函数有两个参数:助记词和盐。其中盐的目的是增加构建能够进行暴力攻击的查找表的困难度。

  1. PBKDF2 密钥延伸函数的第一个参数是从步骤6生成的助记符。

  2. PBKDF2 密钥延伸函数的第二个参数是盐。 由字符串常数“助记词”与可选的用户提供的密码字符串连接组成。

  3. PBKDF2 使用 HMAC-SHA512 算法,使用 2048 次哈希来延伸助记符和盐参数,产生一个 512位的值作为其最终输出。 这个 512 位的值就是种子。

5.2.4 BIP 中可选的可选密码短语

BIP-39 标准允许在推导种子时使用可选的密码短语。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展示一个独立的网页,可以生成助记词、种子和扩展私钥。

BIP-39生成器可以离线使用,也可以使用这个在线地址.地址转向到这儿了

5.3 从种子中创造 HD 钱包

HD 钱包从单个根种子(root seed)中创建,为 128 到 256 位的随机数。最常见的是,这个种子是从助记符产生的,如上一节所述。

HD 钱包的所有的确定性都衍生自这个根种子。任何兼容 HD 钱包的根种子也可重新创造整个 HD钱包。所以简单的转移HD钱包的根种子就让 HD 钱包中所包含的成千上百万的密钥被复制,储存导出以及导入。

下图展示创建主密钥以及HD钱包的主链代码的过程:

5.3.1 私有子密钥的衍生

分层确定性钱包使用 CKD(child key derivation) 函数去从母密钥衍生出子密钥。

子密钥衍生函数是基于单项哈希函数。这个函数结合了:

一个母私钥或者公共钥匙(ECDSA未压缩键)

一个叫做链码(256 bits)的种子

一个索引号(32 bits)

链码是用来给这个过程引入确定性随机数据的,使得索引不能充分衍生其他的子密钥。因此,有了子密钥并不能让它发现自己的姊妹密钥,除非你已经有了链码。最初的链码种子(在密码树的根部)是用随机数据构成的,随后链码从各自的母链码中衍生出来。

母公共钥匙——链码——以及索引号合并在一起并且用 HMAC-SHA512 函数散列之后可以产生512 位的散列。所得的散列可被拆分为两部分。散列右半部分的 256 位产出可以给子链当链码。左半部分 256 位散列以及索引码被加载在母私钥上来衍生子私钥。在下图中,我们看到这个说明——索引集被设为 0 去生产母密钥的第 0 个子密钥(第一个通过索引)。

改变索引可以让我们延长母密钥以及创造序列中的其他子密钥。比如子0,子1,子2 等等。每一个母密钥可以有 231 个子密钥。231 是整个232 范围可用的一半,因为另一半是为特定类型的推导而保留的。向密码树下一层重复这个过程,每个子密钥可以依次成为母密钥继续创造它自己的子密钥,直到无限代。下图阐述了扩展母公钥来衍生子公钥的传递机制:

5.3.2 使用衍生的子密钥

子密钥不能被用来发现他们的母密钥。子密钥也不能用来发现他们的相同层级的姊妹密钥。因为衍生函数是单向的。只有母密钥以及链码才能得到所有的子密钥。没有子链码的话,子密钥也不能用来衍生出任何孙密钥。你需要同时有子密钥以及对应的链码才能创建一个新的分支来衍生出孙密钥。

子密钥可以用来做公钥和比特币地址。之后它就可以被用在那个地址来签署交易和支付任何东西。

5.3.3 扩展密钥

密钥衍生函数可以被用来创造密钥树上任何层级的子密钥。这只需要三个输入量:一个密钥,一个链码以及想要的子密钥的索引。密钥以及链码这两个重要的部分被结合之后,就叫做扩展密钥(extended key)。术语“extended key”也被认为是“可扩展的密钥”,因为这种密钥可以用来衍生子密钥。

扩展密钥可以简单地被储存并且表示为简单的将 256 位密钥与 256 位链码所并联的 512位序列。有两种扩展密钥:

  • 扩展的私钥是私钥以及链码的结合。它可被用来衍生子私钥(子私钥可以衍生子公钥)。
  • 公钥以及链码组成扩展公钥,它可以用来扩展子公钥。

扩展密钥编码用的 Base58Check 使用特殊的版本号,这导致在 Base58 编码字符中,出现前缀“xprv”和“xpub”。这种前缀可以让编码更易被识别。因为扩展密钥是 512 或者 513 位,所以它比我们之前所看到的 Base58Check 编码串更长一些。

5.3.4 公共子密钥推导

两种衍生子公钥的方法:或者通过子私钥,再或者就是直接通过母公钥。

扩展密钥可以在 HD 钱包结构的分支中,被用来衍生所有的公钥(且只有公钥)。

5.3.5 在网店中使用扩展公钥(xpub)

略。

5.3.6 硬化子密钥的衍生

因为扩展公钥包含有链码,如果子私钥被知道或者被泄漏的话,链码就可以被用来衍生所有的其他子私钥。更糟糕的是,子私钥与母链码可以用来推断母私钥。

因此,HD 钱包使用一种叫做硬化衍生(hardened derivation)的替代衍生函数。这就“打破”了母公钥以及子链码之间的关系。这个硬化衍生函数使用了母私钥去推导子链码,而不是母公钥。这就在母/子顺序中创造了一道“防火墙”——有链码但并不能够用来推算子链码或者姊妹私钥。强化衍生函数看起来几乎与一般的衍生的子私钥相同,不同的是母私钥被用来输入散列函数中而不是母公钥,如下图所示:

5.3.7 正常衍生和强化衍生的索引号码

索引号在 0 和 231–1(0x0 to 0x7FFFFFFF) 之间的是只被用在常规衍生。索引号在 231 和 232– 1 (0x80000000 to 0xFFFFFFFF) 之间的只被用在强化衍生。

强化子密钥的索引号码是从 0 开始展示的,但是右上角有一个小撇号。第一个常规子密钥因此被表述为 0,但是第一个强化子密钥(索引号为 0x80000000)就被表示为 0'。第二个强化密钥依序有了索引号 0x80000001,且被显示为 1',以此类推。当你看到 HD 钱包索引号 i',这就意味着 231+i。

5.3.8 钱包密钥识别符(路径)

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 个子密钥。

5.3.9 HD 钱包树状结构的导航

HD 钱包树状结构提供了极大的灵活性。每一个母扩展密钥有 40 亿个子密钥:20 亿个常规子密钥和 20 亿个强化子密钥。 而每个子密钥又会有 40 亿个子密钥并且以此类推。

BIP-43 提出使用第一个强化子索引作为特殊的标识符表示树状结构的“purpose”。基于 BIP-43,HD 钱包应该使用且只用第一层级的树的分支,而且有索引号码去识别结构并且有命名空间来定义剩余的树的目的地。

在 BIP-43 标准下,为了延长的那个特殊规范,BIP-44 提议了多账户结构作为“purpose”。所有遵循 BIP-44 的 HD 钱包依据只使用树的第一个分支的要求而被定义:m/44'/。BIP-44 指定了包含 5 个预定义树状层级的结构:

1
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”,这可以允许使用者为了会计或者组织目的,而去再细分他们的钱包到独立的逻辑性亚账户。每个账户都是它自己亚树的根。

  • 第四层级就是“change”。每一个 HD 钱包有两个亚树,一个是用来接收地址一个是用来创造找零地址。这一层级使用的都是常规衍生。这是为了允许这一层级的树可以在不安全环境下,输出扩展公钥。

  • 被 HD 钱包衍生的可用的地址是第四层级的子级,就是第五层级的树的“address_index”。

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×