首页 > 区块链 > 跟着老廖(廖雪峰)学习区块链(4)教程:私钥
科技无了  

跟着老廖(廖雪峰)学习区块链(4)教程:私钥

摘要:区块链公钥和私钥在比特币中,私钥本质上就是一个256位的随机整数。我们以JavaScript为例,演示如何创建比特币私钥。在JavaScript中,内置的Number类型使用56位表示整数和浮点数,最大可表示的整数最大只有90071。其他语言如Java一般也仅提供64位的整数类型。要表示一个256位

比特币中,私钥本质上就是一个256位的随机整数。我们以JavaScript为例,演示如何创建比特币私钥。

在JavaScript中,内置的Number类型使用56位表示整数和浮点数,最大可表示的整数最大只有90071。其他语言如Java一般也仅提供64位的整数类型。要表示一个256位的整数,只能使用数组来模拟。bitcoinjs使用bigi这个库来表示任意大小的整数。

下面的代码演示了通过ECPair创建一个新的私钥后,表示私钥的整数就是字段d,我们把它打印出来:

const bitcoin = require('bitcoinjs-lib');let keyPair = bitcoin.ECPair.makeRandom();// 打印私钥:console.log('private key = ' + keyPair.d);// 以十六进制打印:console.log('hex = ' + keyPair.d.toHex());// 补齐32位:console.log('hex = ' + keyPair.d.toHex(32));

要在线运行代码,请点击阅读原文并用浏览器访问网页版本

注意:每次运行上述程序,都会生成一个随机的ECPair,即每次生成的私钥都是不同的。

256位的整数通常以十六进制表示,使用toHex(32)我们可以获得一个固定64字节的十六进制字符串。注意每两个十六进制字符表示一个字节,因此,64字符的十六进制字符串表示的是32字节=256位整数。

想要记住一个256位的整数是非常困难的,并且,如果记错了其中某些位,这个记错的整数仍然是一个有效的私钥,因此,比特币有一种对私钥进行编码的方式,这种编码方式就是带校验的Base58编码。

对私钥进行Base58编码有两种方式,一种是非压缩的私钥格式,一种是压缩的私钥格式,它们分别对应非压缩的公钥格式和压缩的公钥格式。

具体地来说,非压缩的私钥格式是指在32字节的私钥前添加一个0x80字节前缀,得到33字节的数据,对其计算4字节的校验码,附加到最后,一共得到37字节的数据:

跟着老廖(廖雪峰)学习区块链(4)教程:私钥

计算校验码非常简单,对其进行两次SHA256,取开头4字节作为校验码。

对这37字节的数据进行Base58编码,得到总是以5开头的字符串编码,这个字符串就是我们需要非常小心地保存的私钥地址,又称为钱包导入格式:WIF(Wallet Import Format),整个过程如下图所示:

跟着老廖(廖雪峰)学习区块链(4)教程:私钥

可以使用wif这个库实现WIF编码:

const wif = require('wif');// 十六进制表示的私钥:let privateKey = '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d';// 对私钥编码:let encoded = wif.encode(        0x80, // 0x80前缀        Buffer.from(privateKey, 'hex'), // 转换为字节        false // 非压缩格式);console.log(encoded);

另一种压缩格式的私钥编码方式,与非压缩格式不同的是,压缩的私钥格式会在32字节的私钥前后各添加一个0x80字节前缀和0x01字节后缀,共34字节的数据,对其计算4字节的校验码,附加到最后,一共得到38字节的数据:

跟着老廖(廖雪峰)学习区块链(4)教程:私钥

对这38字节的数据进行Base58编码,得到总是以K或L开头的字符串编码,整个过程如下图所示:

跟着老廖(廖雪峰)学习区块链(4)教程:私钥

通过代码实现压缩格式的WIF编码如下:

const wif = require('wif');// 十六进制表示的私钥:let privateKey = '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d';// 对私钥编码:let encoded = wif.encode(        0x80, // 0x80前缀        Buffer.from(privateKey, 'hex'), // 转换为字节        true // 压缩格式);console.log(encoded);

目前,非压缩的格式几乎已经不使用了。bitcoinjs提供的ECPair总是使用压缩格式的私钥表示:

const    bitcoin = require('bitcoinjs-lib'),    BigInteger = require('bigi');let    priv = '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d',    d = BigInteger.fromBuffer(Buffer.from(priv, 'hex')),    keyPair = new bitcoin.ECPair(d);// 打印WIF格式的私钥:console.log(keyPair.toWIF());
小结

比特币的私钥本质上就是一个256位整数,对私钥进行WIF格式编码可以得到一个带校验的字符串。

使用非压缩格式的WIF是以5开头的字符串。

使用压缩格式的WIF是以K或L开头的字符串。

免责声明
世链财经作为开放的信息发布平台,所有资讯仅代表作者个人观点,与世链财经无关。如文章、图片、音频或视频出现侵权、违规及其他不当言论,请提供相关材料,发送到:2785592653@qq.com。
风险提示:本站所提供的资讯不代表任何投资暗示。投资有风险,入市须谨慎。
世链粉丝群:提供最新热点新闻,空投糖果、红包等福利,微信:msy2134。