本文简要说明从熵源到比特币地址的形成过程,知识点主要来源于《精通比特币(第二版)》的第四章(密钥和地址)和第五章(钱包)。
由一个随机的熵源(如,128 bits)到 34 字节的比特币地址,简单来说有 6步,如图上半部分所示;而具体到细节,则有几十步之多,如图下半部分。(图片很大,主要是书上的图,下文有局部大图,“比特币源码研读班”知识星球中也上传了)
1、熵源(entropy)
生成私钥的第一步也是最重要的一步,是要找到足够安全的熵源,即随机性来源。这里提到的“随机”一定得是真正的随机,不能是自己根据生日、名言、姓名等特定文本来编造;也不能自己写代码或使用编程语言提供的简易随机数生成器也获得一个随机数。
比特币私钥其实是一个数字。我们可以用硬币、铅笔和纸来随机生成一个私钥。方法是,掷硬币 256 次,用纸和铅笔记录正反面并转换为 0 和 1 ,随机得到的 256 位二进制数字可作为比特币私钥。
这个 256 位二进制数字是一个熵的实例,也是一个私钥,但是不容易记住,对用户不友好。毕竟 256 位是一个很长的数字,即使用十六进制表示也有 64 位之多(256 ÷ 4 = 64)。为了方便记忆,可以把熵源转化为助记词(见第 2 节)。
2、创建助记词(mnemonic)
助记词从由钱包使用 BIP-39 中定义的标准化过程自动生成的。钱包从熵源开始,增加校验和,然后将熵映射到单词列表。
六个步骤是:
- 创建一个 128 到 256 位的随机序列(熵)。
- 提出 SHA256 哈希前几位(熵长 / 32),就可以创造一个随机序列的检验和。
- 将检验和添加到随机序列的末尾。
- 将序列划分为包含 11 位的不同部分。
- 将每个包含 11 位的值与一个已经预先定义 2048 个单词的字典做对应。
- 生成的有序单词组就是助记词。
图中以 128 位熵源举例,检验和取 4 位,创建的助记词为 12 个单词。
取 2048 个单词是因为,每个部分都包含 11 位,2 的 11 次方是 2048 。这样就每一部分的值都对应于一个单词。
3、从助记词生成种子(seed)
助记词又怎么和私钥联系起来呢?通过种子。
助记词表示长度为 128 至 256 位的熵。通过使用密钥延伸函数 PBKDF2 ,熵被用于导出较长的(512位)种子。所得到的种子用于构建确定性钱包,并得到其私钥。
密钥延伸函数有两个参数:助记词和盐。其中盐的目的是增加能够进行暴力攻击的难度。在 BIP-39 中,盐有另一目的,它允许引入密码短语(passphrase)。
从助记词生成种子分为三步:
- PBKDF2 密钥延伸函数的第一个参数是从步骤 6 生成的助记词。
- PBKDF2 密钥延伸函数的第二个参数是盐,由字符串常数“助记词”与可选的用户提供的密码字符串连接而成。
- PBKDF2 使用HMAC-SHA512 算法,使用 2048 次哈希来延伸助记词和盐参数,产生一个 512 位的值作为其最终输出。这个 512 位的值就是种子。
4、种子到主私钥(Master Private Key “m”)
HD钱包从根种子中创建,就是前一节中生成的种子。HD钱包的所有的确定性都衍生自这个根种子。任何兼容HD钱包的根种子也可重新创建整个HD钱包。上图展示了创建主私钥和主链编码的过程。
主私钥(m)之后,可以通过椭圆曲线 m*G 过程来生成相对应的主公钥(M)。链码用于从母私钥中创建子私钥的那个函数中引入熵。
5、HD钱包
HD钱包包含以树状结构衍生的密钥,使得父密钥可以衍生一系列子密钥,每个子密钥又可以衍生出一系列孙密钥,以此类推,无限衍生。
(这部分内容还有很多地方没搞懂,后期再补上笔记。。。)
6、私钥的 Base58Check 编码
一个 256 位二进制的私钥,以十六进制表示是 64 位(256 ÷ 4 = 64),占用 32 字节。(如图)举例为:1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD 。
私钥的 Base58Check 编码过程如图,其中前缀是 0x80,对于压缩类型的私钥,要加后缀 0x01。接下来,计算两次 SHA256 ,取前四个字节做为校验和,添加到数据后面,再对结果用 Base58 字母表编码。
得到的 Base58Check 私钥,非压缩类型以 5 开头,压缩类型以 K 或 L 开头。
6、公钥到公钥哈希
K = k * G 的结果中,K由一对坐标(x, y)组成,而 x 和 y 有数学关系,于是 y 可以略去,这就是压缩公钥。非压缩格式公钥用 04 作为前缀,压缩格式公钥以 02 或者 03 作为前缀。 非压缩格式公钥占 65 字节(1 + 32 + 32),压缩格式公钥占 33 字节(1 + 32)。
再将数据做一次 SHA256,做一次 RIPEMD160 运算得到公钥哈希,160 位,20字节。
7、公钥哈希到比特币地址
以 160 公钥哈希加上前缀 0x00做为输入,计算两次 SHA256 取前四个字节加到后面,对这个 25 字节的数据用 Base58 编码,就得到了 34 字节的比特币地址,以 1 开头。举例:1PRTTaJesdNovgne6Ehcdu1fpEdX7913CK 。
参考资料:
《精通比特币(第二版)》 - 区块链研习社×云天明© 联合出品
掘金小册:《数字货币与区块链原理》 - 廖雪峰
《区块链开发指南》- 申屠青春 主编
不足之处,请批评指正,谢谢。
区块链研习社比特币源码研读班 刘纪祥