Bitcoin and Key Management
比特币提供了匿名性,但是匿名性很差,使用多个私钥会获得较好的匿名性。但是如果比特币钱包包含的是随机生成的私钥,将会产生大量的私钥,在实际中很难管理,并且占用大量储存空间。所以找到一个好的解决方法至关重要。在较早的一批比特币客户端中,使用的是随机生成私钥的集合的钱包,这种钱包被称为零型非确定型钱包,它的缺点就是如果你生成很多私钥,就必须要保存它们的副本,不然私钥丢失里面的比特币也将付诸东流,并且这种情况与避免重复使用地址相冲突,地址关联多重交易和对方地址重复使用会减少隐私,也就是降低匿名性,所以这种钱包不是一种很好的选择,下面为大家介绍解决方法——确定性钱包
确定性的私钥管理
优点
- 限制了私钥的公开程度,并且限制了攻击者可以针对传统算法攻击和旁路攻击进行处理
- 大大节省了存储空间
Type1
通过对种子和索引$n$哈希生成索引所对应的私钥。我们可以利用种子来将所有的私钥恢复,所以在备份的时候只需要备份种子就可以了。这样的话极大减少了备份私钥的空间,并且有利于钱包的管理,但是也有致命性的缺点如果种子被盗取,那么将造成钱包中所有私钥的泄漏!!!
我们的目标是希望能够生成用于接收大量不同交易的比特币唯一私钥,这将增加交易的匿名性。
这种类型我们还以用作种子生成主私钥,然后主私钥生成子私钥,以此类推,子私钥可以生成孙私钥,这样的话就可以得到无穷无尽并且很方便管理的私钥群。并且不同的分支用作不同的用途,将更加方便我们的生活。
Type2
我们希望有2个推导函数。例如,无论是通过Public派生函数计算还是从SK3计算得出,PK3都应该相同,并且公共种子不应泄露私有种子或任何私有密钥,所有的推导函数都由单向函数来完成。
除了公钥、私钥外,它们还有其它的链值,如下图,因此,知道ECDSA的私钥也不能解出其它的私钥,但是如果seed遭到泄漏之后,那么会造成所有私钥的泄漏,造成严重的后果。并且允许为单个交易生成单个私钥。
解决方法
Definition
我们将扩展私钥定义为:$Extended Private Key=(private key +xc)$
扩展公钥是:$Extended Public Key=(Extended Private Key+xc)$
定义$N$为扩展私钥转换成扩展公钥的操作,所以我们有:
$N (k||xc) = (k.G||xc)$
Solution
其中HM是HMAC,利用哈希算法,以一个秘钥和一个消息为输入生成一个消息摘要作为输出。
前面的公式:$N(k||xc)=(K||xc)$,可以转换成:$N(k_i,c_i)=(K_i,c_i)$
具体过程:$k_i.G=(y_{l_i}*k_L).G=y_{l_i}.(k_L.G)=y_{l_i}.K_L=K_i$ 所以可以得到上面的结果,其中定向的路径都可以生成完全相同的公钥
其中的具体过程:$k_i.G=(y_{L_i}+k_L).G=y_{L_i}.G+k_L.G=y_{L_i}.G+K_L=K_i$
即可以得到:$N(k_i,c_i)=(K_i,c_i)$
HD钱包
分层确定性钱包使用CKD(child key derivation)方程去从母密钥衍生出子密钥。
子秘钥的衍生方程式基于单向哈希方程,主要有以下几部分组成:
- 一个母私钥
- 一个叫做链码的种子
- 一个索引号
所以只有私钥和索引并不能衍生出所有的私钥,还需要链码。
扩展密钥(BIP32)
为了防止密钥衍生仅依赖于自身,协议中引入了一个256位的熵,称为链码。$key||chain_{code}$
衍生:$(key_{child},chain_{codechild})=CKD((key_{parent},chain_{codeparent}),index)$ 这是扩展私钥的衍生过程对应于上图中的数据。扩展公钥的衍生过程与其同理。
普通衍生的索引范围是:$0-(2^{31}-1)$
如果子私钥泄漏,且扩展公钥中含有链码,所以攻击者就可以利用私钥+链码衍生出所有的后续私钥,同时可以利用链码和子私钥猜测母私钥。所以又出现了“硬化子秘钥的衍生”
硬化子秘钥的衍生
它是利用母私钥直接去计算子链码,而不是利用母公钥,这样就使得链码不会暴露,所以也就无法利用私钥去进一步衍生其他私钥。
硬化衍生索引的范围是:$2^{31}-2^{32}$
小结
公式:母私钥生成子私钥
$key_i,chain_{code_i}=CKD((key_{parent},chain_{code_{parent}}),i)$
- 如果$i \geq2^{31}$,要进行硬化衍生,获得新序列:
$I=HMAC-SHA512(key=chain_{code_{parent}},data=0x00||ser_{256}(key_{parent})||ser_{32}(i))$ - 如果$i\leq2^{31}$,则要进行普通衍生获得新序列:
$I=HMAC-SHA512(key=chain_{code_{parent}},data=ser_p(point(key_{parent}))||ser_{32}(i))$ - 最后将$I$分为两部分$(I_L,I_R)=I$
$I_R$即为子密钥的$chain_{code}$
$I_L$和母私钥及索引可以推算出子私钥