区块链学习(2)钱包
比特币中的钱包并不包含比特币,只包含私钥,每一个用户有一个包含多个私钥的钱包。钱包中包含成对的私钥和公钥。用户用这些私钥来签名交易。可以说钱包是私钥的容器。
最开始的钱包只储存随机生成的私钥。这种类型的钱包被称作零型非确定钱包。从名字中就可以看出,这种钱包从最开始就生成足够多的私钥,私钥都是随机产生的。但这种钱包的缺点很明显,为了增加安全性,每次交易都使用不同的地址,而一个私钥对应一个地址,可以看下图。
就是如果你生成很多私钥,你必须保存它们所有的副本。钱包中的每一把钥匙都必须备份。非确定性的钱包私钥之间是没有任何关系的,所以你需要备份所有不同的私钥,十分麻烦。而确定性钱包就很好的解决了这个问题,确定性钱包也称为种子钱包。这个钱包的特点就是随机生成一个的种子数,这个种子便可以通过哈希方程计算出很多私钥,于是只要备份一个种子就行了。
助记码词汇对应确定性钱包的种子。一般由12、15、18、21个单词构成,这些单词都取自一个固定词库,其生成顺序也是按照一定算法而来。也可以被用来恢复以及重新创造应用程序相同或者兼容的钱包的钥匙。助记码代码可以让使用者复制钱包更容易一些, 因为助记词比私钥更容易记忆。PBKDF2 (Password-Based Key Derivation Function 2) 的基本原理是通过一个为随机函数(例如 HMAC 函数),把明文和盐值作为输入参数,然后重复进行运算最终产生密钥。
为了从助记词中生成二进制种子,BIP39 采用 PBKDF2 函数推算种子,其参数如下:
- 助记词句子作为密码
- "mnemonic" + passphrase 作为盐
- 2048 作为重复计算的次数
- HMAC-SHA512 作为随机算法
- 512 位(64 字节)是期望得到的密钥长度
种子钱包的一个优点就是只需要备份一个种子便可以恢复所有的私钥。
现在大部分钱包都是HD钱包了,全称the hierarchical deterministic wallet,私钥衍生结构是树状结构,父密钥可以衍生一系列子密钥,每个子密钥又可以衍生出一系列孙密钥,以此类推,无限衍生。
上图就是HD钱包,与我们学过的数据结构中的多叉树很像。生成一个子密钥需要一个母私钥或者公共钥匙,一个叫做链码(256 bits)的种子,一个索引号(32 bits)。这三个项目相结合并散列可以生成子密钥,
这里采用的也是单向的哈希函数,应此不能从子密钥中推出母密钥。上述方法中通过推导出的私钥可推导出对应公钥,但 HD 钱包优点之一就是在隐藏私钥的前提下通过公钥推导出子公钥,这样私钥的离线储存更加安全。具体来说,你的主私钥是以纸钱包的方式备份的,并且离线存放在一个安全的地方。你手头有主公钥,用这个公钥,你就可以生成所有的子公钥。 举个实际的例子,我们要开一个网店,接受比特币付款。你可以离线存放你的私钥,只需要提供公钥,你的网站可以使用这个公钥为网站上的每一个商品生成一个收款地址,或者给你的每个顾客生成一个唯一的地址。上次已经讲过公钥无法推出私钥, 并且因为私钥是离线存放的,没人可以黑进你的服务器偷走比特币。
但是这种推导方式存在问题。
- 虽然泄漏公钥并不会导致丢币,但含有公钥的扩展密钥泄漏会导致以此为根节点推导出来的扩展公钥全部泄漏,一定程度上破坏了隐私性。
- 泄漏扩展公钥加上该公钥推导出的后任一代扩展公钥对应的私钥有被推导出该扩展公钥的所有后代私钥的可能性
BIP32 协议把 CKD 函数改为 HKD (hardened key derivation formula) 生成增强密钥推导函数。
上图就是采用HKD的推导过程,与之前未强化的推导过程相比不同的是是母私钥被用来输入散列方程中而不是母公钥。