钱包原理——助记词与公私钥

目前钱包分为两种:
一种是非确定性(随机)的钱包,就是随机生成多个私钥,钱包管理这些私钥。如果需要成千上万的地址,通过随机的方式来生成私钥,这就需要存储那么多无规律的私钥,这样就很麻烦不好管理。
另一种是确定性(种子)的钱包,就是通过种子可以生成无数的私钥,我们只需要记住种子就可以了。我们在使用钱包时记住的助记词可以生成种子,只要我们保管好助记词,我们的币就能找回来。用一句话来解释助记词:它是私钥的明文显示。

主要流程

1、随机生成128到258位的随机数,称作熵;
2、熵经过一定处理方法,生成助记词;
3、助记词经过密钥延伸函数PBKDF2,生成种子;
4、种子经过HMAC-SHA512算法,生成母密钥;
5、通过CKD(child key derivation)函数,母密钥生成众多子密钥。

从熵到助记词

1、生成一个128到256位的数字,叫做熵,熵的长度是32的整数倍,分别为 128, 160, 192, 224, 256,也就是我们私钥的长度。
在这里插入图片描述
2、熵通过SHA256哈希得到一个值,取前面的几位(熵长/32),称为校验和, 所以校验和长度可为 4,5,6,7,8 位。
在这里插入图片描述
3、校验和加入熵的末尾,组成一个新的序列。
在这里插入图片描述
4、将新序列以11位为一部分,与已经预先定义2048个单词的字典做对应。
在这里插入图片描述
5、生成的有顺序的单词组就是助记词。

从助记词到种子

通过使用密钥延伸函数PBKDF2,熵被用于导出较长的(512位)种子。
PBKDF2的基本原理是通过一个伪随机函数(例如HMAC-SHA512函数),把明文和一个盐值作为输入参数,然后重复进行运算,并最终产生密钥。如果重复的次数足够大,破解的成本就会变得很高。而盐值的添加也会增加“彩虹表”攻击的难度。

DK = PBKDF2(PRF, Password, Salt, c, dkLen)

PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果。

Password是用来生成密钥的原文密码。

Salt是一个加密用的盐值。

c是进行重复计算的次数。

dkLen是期望得到的密钥的长度。

DK是最后产生的密钥。

在这里插入图片描述
DK的值由一个以上的block拼接而成。block的数量是dkLen/hLen的值。就是说如果PRF输出的结果比期望得到的密钥长度要短,则要通过拼接多个结果以满足密钥的长度:

DK = T1 || T2 || … || Tdklen/hlen

而每个block则通过则通过函数F得到:

Ti = F(Password, Salt, c, i)

在函数F里,PRF会进行c次的运算,然后把得到的结果进行异或运算,得到最终的值。

F(Password, Salt, c, i) = U1 ^ U2 ^ … ^ Uc

第一次,PRF会使用Password作为key,Salt作为盐值进行运算。

U1 = PRF(Password, Salt)

而后续的c-1次则会使用上次得到的结果作为盐值。

U2 = PRF(Password, U1)

Uc = PRF(Password, Uc-1)
在这里插入图片描述
这个最终生成的值就是种子。

从种子到母密钥

种子通过不可逆 HMAC-SHA512 算法推算出 512 位的哈希串,左 256 位是主私钥Master Private key(m), 右 256 位是主链码 master chain code, 通过 m 结合推导公钥的椭圆曲线算法能推导出与之对应的 264 位主公钥master public Key (M)。chain code 作为推导下级密钥的熵。

子私钥推导

使用 CKD(child key derivation) 函数从父密钥(parent keys)推导子密钥(child keys),CKD 由下列三个要素做单向散列哈希(one way hash function) 。
•父密钥 (没有压缩过的椭圆曲线推导的私钥或公钥 ECDSA uncompressed key)
•链码作为熵 (chain code 256 bits)
•子代索引序号 (index 32 bits)
索引号个数为 2 的 32 次方,每个父级密钥能推导出该数目一半的子密钥。
索引号从 0x00 到 0x7FFFFFFF (0 to 2 的 21 次方减 1) 会生成正常的密钥;索引号从 0x80000000 到 0xFFFFFFFF 会生成增强密钥 )。
通过SHA512哈希生成的字符串,又进一步拆分成左右两个部分,左部分与父私钥相加,成为子私钥;右部分直接作为主链码,用于生成下一级的子私钥。
CKD 采用不可逆的 HMAC-SHA512 不可逆加密算法,子密钥不能向上推导出父密钥、同时也不能水平推导出同一级的密钥。
在这里插入图片描述

扩展密钥

CKD 推导子密钥的三个元素中,其中父密钥和链码结合统称为扩展密钥 (Extended keys)。256 位的密钥和 256 位的链码串联起来的 512 位就是扩展密钥
1.包含私钥的扩展密钥用以推导子私钥,从子私钥又可推导对应的公钥和比特币地址
2.包含公钥的扩展密钥用以推导子公钥

扩展密钥使用 Base58Check 算法加上特定的前缀编码,编码得到的包含私钥的前缀为 xprv, 包含公钥的扩展密钥前缀为 xpub,相比比特币的公私钥,扩展密钥编码之后得到的长度为 512 或 513 位。

子公钥推导

上述方法中通过推导出的私钥可推导出对应公钥,但在隐藏私钥的前提下同样可以通过公钥推导出子公钥,极大加强安全性。在只需要生成地址接受比特币而无权消费的场景下非常有用,通过公钥扩展密钥能生成无穷尽的公钥和比特币地址。

子私钥推导流程和子公钥流程基本一样,差异之处有两点:
1.把子私钥推导过程中私钥替换为公钥。
2.子公钥推导出对应出与之的子链码
在这里插入图片描述

增强扩展密钥推导

密钥需加强保管以免泄漏,泄漏私钥意味着对应的地址上的币可被转走、泄漏公钥意味着钱包的隐私被泄漏。增强密钥推导 (Hardened child key derivation) 解决下述两个问题:
1.虽然泄漏公钥并不会导致丢币,但含有公钥的扩展密钥泄漏会导致以此为根节点推导出来的扩展公钥全部泄漏,一定程度上破坏了隐私性。
2.泄漏扩展公钥加上该公钥推导出的后任一代扩展公钥对应的私钥有被推导出该扩展公钥的所有后代私钥的可能性。

于此,BIP32 协议把 CKD 函数改为 HKD (hardened key derivation formula) 生成增强密钥推导函数。

CKD 函数以推导扩展密钥的序列号 ( 0x00 到 0x7FFFFFFF)、父链码和父公钥生或父私钥成子链码和子公钥,子私钥从父私钥推导;而 HKD 通过父私钥、父链码和推导增强扩展密钥的序列号 (0x80000000 到 0xFFFFFFFF) 增强子私钥和增强子链码。
在这里插入图片描述

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读