这篇文章,参考《精通比特币》,加入了一些自己的理解和注释。
先从钱包开始写,是因为自己正在做钱包,这里是钱包的入口。
本人知识有限,如有错误和疏漏,请务必指正,多谢。
什么是非确定性钱包
非确定性指的是,无法从一个私钥推导出另一个私钥,也就是私钥是完全随机生成的。
比特币为了保护交易隐私,要求地址不能重复使用(也就是每次交易之后,改变地址),因为每个地址对应一对公私钥,所以变更地址,就是变更公私钥对,所以钱包里就存在大量的私钥,Just a Bunch of Keys (一堆私钥),简称 JBOK。
为什么从非确定性(随机)钱包,过渡到确定性钱包
每个私钥都对应着一笔资金,所有私钥都得妥善保存,但是在非确定钱包里因为私钥间是没有关联的,所以所有私钥都需要备份,而且因为私钥在不断产生,需要经常备份,要不就有可能丢失私钥。
正是因为管理的麻烦,所以催生了确定性钱包,确定性钱包里的私钥是可以由主私钥一层层推导出来的,所以只需要保存好主私钥即可。
分层确定性钱包的生成过程
HD 钱包需要一个种子来产生主密钥,然后逐层产生子密钥,在知道种子的情况下,每层的密钥中的每一个都可以确定下来,所以叫确定性钱包。
而种子的产生需要助记词,助记词的产生是根据 BIP0039 来做的(BIP0039在另一篇文章里介绍),流程可以看下图:
熵是由 CSPRNG (密码学安全的伪随机数生成器)产生,就是一个随机数。
需要注意的是,熵和助记词可以互相转化,但是助记词到种子是个单向的过程,种子到主私钥也是个单向过程
链码是用来给这个过程引入看似的随机数据的,使得索引不能充分衍生其他的子密钥。因此,有了子密钥并不能让它发现自己的相似子密钥,除非你已经有了链码(这个导致了硬化子密钥的产生)。最初的链码种子(在密码树的根部)是用随机数据构成的,随后链码从各自的母链码中衍生出来。
索引为0,就是生成第0个子密钥。
分层确定性钱包的一些特性
首先子私钥不能从非确定性(随机)密钥中被区分出来。因为衍生方程是单向方程,所以子密钥不能被用来发现他们的母密钥。子密钥也不能用来发现他们的相同层级的姊妹密钥。
分层确定性钱包的一个很有用的特点就是可以不通过私钥而直接从公共母钥匙派生出公共子钥匙的能力。这就给了我们两种去衍生子公共钥匙的方法:或者通过子私钥,再或者就是直接通过母公共钥匙。
这个方法真的非常重要,使钱包的使用非常灵活,比如可以在某个应用或者服务器上部署一个公钥,然后应用或者服务器可以自行扩展公钥来进行业务,但是因为没有私钥,服务器和应用无法使用这个地址上的比特币。
但是这种灵活性也有弊端,就是在丢失任意一个子私钥的情况下,那么所有母私钥和其他子私钥都可以推导出来,看下图:
深绿色的是原本就知道信息,如果额外知道了浅绿色的子私钥信息,那么就可以反向推导出来父私钥(减去“左256 bits”),那么所有其他的子私钥也就知道了。这种推导可以一直延续到主私钥!
所以为了应对这种风险,HD钱包使用一种叫做 hardened derivation 的硬化衍生方案。这就“打破”了母公共钥匙以及子链码之间的关系。这个硬化衍生方程使用了母私钥去推到子链码,而不是母公共钥匙。这就在母/子顺序中创造了一道“防火墙”——有链码但并不能够用来推算子链码或者姊妹私钥。强化的衍生方程看起来几乎与一般的衍生的子私钥相同,不同的是是母私钥被用来输入散列方程中而不是母公共钥匙,如下图:
这样就是牺牲掉了灵活性,保证了安全性。那就不要灵活性了么?其实可以兼顾灵活性和安全性。因为钱包是分层的,所以可以在前面层上使用硬化衍生,而在后面层上使用正常衍生,一般是在 account 的下一层 change 层开始使用正常衍生,这样就算丢失密钥,也只是丢失当前 account 的所有密钥,不会影响到其他 account。
BIP0044 中指定了包含5个预定义树状层级的结构:
m / purpose’ / coin_type’ / account’ / change / address_index
分别是:目的地(默认44‘),货币种类(0’是比特币),账户,地址类型(0是接收地址,1是找零地址),地址
这里的\('\),代表是硬化衍生,所以就是从第 4 层开始使用的是正常衍生。一些例子:
参考链接: