比特币钱包及密钥管理知识

前置知识

这部分主要介绍开发钱包之前需要知道的几个知识点。

比特币私钥,公钥和地址之前的关系

比特币中使用椭圆曲线密码学做为公私钥的核心算法(所采用的椭圆曲线是 Secp256k1),私钥本质是一个大的随机数,保密存储,用于签名交易,从而证明 UTXO 的所有权。公钥为椭圆曲线上一点坐标,通过私钥和所在曲线计算得来,这个计算是不可逆的,即不存在一种计算方式从公钥算出所在私钥。通常这里私钥是 32Byte,而公钥是 33Byte(压缩公钥格式),比特币地址本质是公钥的哈希结果;这里使用的哈希是 sha256 + ripemd160.即常说的双哈希,或者又叫哈希160.地址通常表示为哈希结果的 Base58Check 编码方式。

在这里插入图片描述

到底比特币钱包和其功能究竟是什么呢?

比特币钱包是存储和使用比特币的工具,定义清晰而简单,只不过是被大家搞复杂了而已。

比特币钱包就是一个电脑或手机的客户端,安装以后,客户端会自动生成用户的比特币wallet钱包文件,存放用户的比特币信息,包括收款地址、私钥。这个wallet文件就是用户的钱包。比如,从OKCoin上面买了比特币,就可以将比特币转到自己的收款地址上,待网络确认,比特币就会存到用户的wallet钱包里。

总之,比特币钱包的基本功能有两个:一个是安全地保存比特币私钥,另一个是用来收发比特币。

实现钱包密钥管理的几个标准

现阶段,对于开发钱包来说,有几个事实标准需要遵守和实现,而且现有市面上钱包都是实现这样的几个标准的

BIP-0032: 分层确定性钱包(HD钱包)规范;

BIP-0039: 私钥与助记词(mnemonic code)相互转换的规范;

BIP-0043: 多用途 HD 钱包规范;

BIP-0044: 多账户多币种 HD 钱包规范;

这几个规范基本现有的钱包都会实现,其中 BIP-0032、BIP-0038、BIP-0039 之间相互独立,处于钱包实现的不同流程;BIP-0043 是在 BIP-0032 上制定的规范,BIP-0044 又基于 BIP-0043 而制定了更详细的一个规范;和 BIP-0044 同类型的还有 BIP-0045、BIP-0047、BIP-0049 等几种规范;

  1. BIP-0032

比特币建议的同一个地址使用一次,相较于普通的 私钥 -> 公钥 -> 地址 的这一关系,钱包需要维护多个地址,所以钱包有两个方向可以做,一种是存储独立的多个私钥,从而对应多个地址,这也就是非确定性钱包;另一种思路是一个种子(Seed)可以扩展产生多个私钥,每个私钥又有自己的对应公钥、地址,这就是确定性钱包;BIP-0032 制定了一种具有分层的确定性钱包规范。

使用非确定性钱包有两个缺点,每个地址对应一个私钥,需要备份的私钥比较多,丢失其中一个私钥,也会损失那部分比特币;私钥在使用过程中不断生成,也需要不时进行备份。

HD 钱包的种子本质还是随机数,或者从别的规范产生的一个数字,最常见是通过 BIP-0039 的助记词产生的;

首先,种子通过 HMAC-SHA512(Key=”Bitcoin seed”, Data=Seed) 哈希函数产生一个 64Byte 的主密钥(Key 是一个确定的字符串 “Bitcoin seed”),主密钥分割成 32Byte 的两部分,左侧用作主私钥,右侧用作衍生子密钥,称为链码(chain code), 左侧的主私钥可以计算出公钥,从而计算出地址来正常使用;主密钥和链码,再结合子密钥索引(索引是一个 4Byte 序号),通过 HMAC-SHA512 衍生出子密钥,这里主要分为三种类型:

(1). 父级私钥 –> 子级私钥

这里还是使用 HMAC-SHA512 哈希函数,父级的 ChainCode 作为哈希函数的 Key,父级私钥计算得到的公钥(33Byte)和索引拼起来用作哈希函数的 Data,哈希函数同样产生一个 64Byte 的子密钥,同样分割为 32Byte 的两部分,右侧的 ChainCode 用作于子链衍生自己的子链;左侧通过和父级私钥进行数字相加得到子级私钥;这里子级私钥有个椭圆曲线和是否为零的校验;校验通过则是一个合法的子级私钥,不合法则会跳过当前索引。

(2). 父级公钥 –> 子级公钥

这里 HMAC-SHA512 的计算和 (1) 中一致,只是这里父级公钥直接参与计算,而不是从私钥推算;同样哈希函数分为两部分,右侧为 ChainCode,左侧的 32Byte 通过椭圆曲线计算出公钥,再和父级公钥通过椭圆曲线的点坐标加法从而得到子级的公钥;

所以这里在使用中就可以只通过父级公钥和链码在不安全环境下衍生需要的子级公钥,全程不需要私钥的参与;这里有个需要明白的,得到的子级公钥在使用中需要私钥来解密,通过 (1) 中同样的索引,计算出来的子级私钥和这里计算的子级公钥就是一个公私钥对;因为这里的椭圆曲线是个可交换群,满足交换律和结合律,而椭圆曲线中私钥计算公钥是一个乘法(PubKey = PrevKey * P, P 是特定椭圆曲线上常数),所以这里满足 ParentPrevKey * P + LeftBytes * P = (ParentPrevKey + LeftBytes) * P,其中 LeftBytes * P 即为左侧的 32Byte 通过椭圆曲线计算的公钥;

(3). 父级私钥 –> 子级公钥

父级私钥得到子级公钥有两种途径,一种途径是先经过 (1),衍生出子级私钥从而计算出子级公钥;另一种途径先计算出父级公钥,再通过 (2) 衍生出子级公钥;

强化衍生

前面提到的父级公钥和链码合起来称为扩展公钥,在不安全环境下来衍生子公钥,但一旦子私钥被泄漏,和扩展公钥中的链码就可以衍生它的所有子私钥,另外子私钥和父级链码有推断出父级私钥的风险,所以又引入了强化衍生的概念。

强化衍生只能从父级私钥衍生子级私钥,从而得到子级公钥,而不能做如上 (2) 中的公钥衍生,具体的衍生过程和 (1) 中 HMAC-SHA512 有细微区别,不同于 (1) 中的父级私钥计算得到的公钥(33Byte),强化衍生通过 0x00 这样 1Byte 拼上私钥和索引作为 Data,其他衍生步骤一致。强化衍生不会将父级链码暴露到不安全的环境下,所以相较于正常衍生更安全些。

子密钥的索引号码和路径表示

索引的范围有 2^32 个,其中前 2^31 表示正常衍生,通常表示为索引序号即可;后 2^31 表示强化衍生,强化衍生序号也是从 0 开始,会在序号后添加撇号表示强化衍生,例如 0x80000000 为第一个强化衍生的序号,通常表示为 0’,钱包中有 i’=2^31+i 这样的关系。

子密钥的路径通过 / 分割的索引表示;前缀有 m 和 M 之分,m 表示衍生的子私钥,M 表示衍生的子公钥。例如 m/5/4’/0 表示子私钥 m/5/4′ 的第 0 个正常衍生私钥,m/5/4′ 则是子私钥 m/5 的第 4 个强化衍生的子私钥,m/5 则是主私钥第 5 个正常衍生的子私钥。

文章转载:www.dltsg.com

猜你喜欢

转载自blog.csdn.net/eostalk8181/article/details/108346639