HD钱包
编辑教程HD钱包
在比特币的链上,实际上并没有账户的概念,某个用户持有的比特币,实际上是其控制的一组UTXO,而这些UTXO可能是相同的地址(对应相同的私钥),也可能是不同的地址(对应不同的私钥)。
出于保护隐私的目的,同一用户如果控制的UTXO其地址都是不同的,那么很难从地址获知某个用户的比特币持币总额。但是,管理一组成千上万的地址,意味着管理成千上万的私钥,管理起来非常麻烦。
能不能只用一个私钥管理成千上万个地址?实际上是可以的。虽然椭圆曲线算法决定了一个私钥只能对应一个公钥,但是,可以通过某种确定性算法,先确定一个私钥k1,然后计算出k2、k3、k4……等其他私钥,就相当于只需要管理一个私钥,剩下的私钥可以按需计算出来。
这种根据某种确定性算法,只需要管理一个根私钥,即可实时计算所有“子私钥”的管理方式,称为HD钱包。
HD是Hierarchical Deterministic的缩写,意思是分层确定性。先确定根私钥root,然后根据索引计算每一层的子私钥:
root
│
├─────────────┬─────────────┐
│ │ │
▼ ▼ ▼
k0 k1 k2 ...
│ │ │
├──┬──┐ ├──┬──┐ ├──┬──┐
│ │ │ │ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
k0 k1 k2 ... k0 k1 k2 ... k0 k1 k2 ...
对于任意一个私钥k,总是可以根据索引计算它的下一层私钥kn:
k_n=hdkey(k,\;n)k
n
=hdkey(k,n)
即HD层级实际上是无限的,每一层索引从0~232,约43亿个子key。这种计算被称为衍生(Derivation)。
现在问题来了:如何根据某个私钥计算下一层的子私钥?即函数hdkey(k, n)如何实现?
HD钱包采用的计算子私钥的算法并不是一个简单的SHA-256,私钥也不是普通的256位ECDSA私钥,而是一个扩展的512位私钥,记作xprv,它通过SHA-512算法配合ECC计算出子扩展私钥,仍然是512位。通过扩展私钥可计算出用于签名的私钥以及公钥。
简单来说,只要给定一个根扩展私钥(随机512位整数),即可计算其任意索引的子扩展私钥。扩展私钥总是能计算出扩展公钥,记作xpub:
xprv ────────> xpub
│ │
│ │
│ │
▼ ▼
xprv-0 ──────> xpub-0
从xprv及其对应的xpub可计算出真正用于签名的私钥和公钥。之所以要设计这种算法,是因为扩展公钥xpub也有一个特点,那就是可以直接计算其子层级的扩展公钥:
xpub
│
├───────┬───────┐
│ │ │
▼ ▼ ▼
xpub-0 xpub-1 xpub-2 ...
因为xpub只包含公钥,不包含私钥,因此,可以安全地把xpub交给第三方(例如,一个观察钱包),它可以根据xpub计算子层级的所有地址,然后在比特币的链上监控这些地址的余额,但因为没有私钥,所以只能看,不能花。
因此,HD钱包通过分层确定性算法,实现了以下功能:
- 只要确定了扩展私钥xprv,即可根据索引计算下一层的任何扩展私钥;
- 只要确定了扩展公钥xpub,即可根据索引计算下一层的任何扩展公钥;
- 用户只需保存顶层的一个扩展私钥,即可计算出任意一层的任意索引的扩展私钥。
从理论上说,扩展私钥的层数是没有限制的,每一层的数量被限制在0~232,原因是扩展私钥中只有4字节作为索引,因此索引范围是0~232。
通常把根扩展私钥记作m,子扩展私钥按层级记作m/x/y/z等:
m
│
├──────────────────────┐
│ │
▼ ▼
m/0 m/1 ...
│ │
├─────┬─────┐ ├─────┬─────┐
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
m/0/0 m/0/1 m/0/2 ... m/1/0 m/1/1 m/1/2 ...
例如,m/0/2表示从m扩展到m/0(索引为0)再扩展到m/0/2(索引为2)。
安全性
HD钱包给私钥管理带来了非常大的方便,因为只需要管理一个根扩展私钥,就可以管理所有层级的所有衍生私钥。
但是HD钱包的扩展私钥算法有个潜在的安全性问题,就是如果某个层级的xprv泄露了,可反向推导出上层的xprv,继而推导出整个HD扩展私钥体系。为了避免某个子扩展私钥的泄漏导致上层扩展私钥被反向推导,HD钱包还有一种硬化的衍生计算方式(Hardened Derivation),它通过算法“切断”了母扩展私钥和子扩展私钥的反向推导。HD规范把索引0~231作为普通衍生索引,而索引231~232作为硬化衍生索引,硬化衍生索引通常记作0'、1'、2'……,即索引0'=231,1'=231+1,2'=231+2,以此类推。
因此,m/44'/0表示的子扩展私钥,它的第一层衍生索引44'是硬化衍生,实际索引是231+44=2147483692。从m/44'/0无法反向推导出m/44'。
在只有扩展公钥的情况下,只能计算出普通衍生的子公钥,无法计算出硬化衍生的子扩展公钥,即可计算出的子扩展公钥索引被限制在0~231。因此,观察钱包能使用的索引是0~231。
BIP-32
比特币的BIP-32规范详细定义了HD算法原理和各种推导规则,可阅读此文档以便实现HD钱包。
选择支付方式:
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间