在
比特币中,私钥是一个256位的随机整数。JavaScript内置的Number类型仅支持56位整数和浮点数,而其他语言如Java仅提供64位整数类型。因此,我们需要使用数组来模拟一个256位整数。比特币JS库使用bigi库来表示任意大小的整数。
下面的代码演示了如何使用ECPair创建一个新的比特币私钥。私钥的整数表示为字段d:
const bitcoin = require("bitcoinjs-lib");
let keyPair = bitcoin.ECPair.makeRandom;
console.log("私钥: " + keyPair.d); // 十进制表示
console.log("私钥: " + keyPair.d.toHex); // 十六进制
console.log("私钥: " + keyPair.d.toHex(32)); // 补全32位
请注意:每次运行上述代码都会生成一个随机的私钥,因此生成的私钥是不同的。
256位的整数通常使用十六进制表示。使用toHex(32)方法可以获得一个固定64字节的十六进制字符串。注意每两个十六进制字符表示一个字节,因此,64字符的十六进制字符串表示的是32字节=256位的整数。
记住一个256位整数非常困难,而且,如果其中某些位有误,这个私钥仍然是一个有效的私钥。因此,比特币采用带校验的Base58编码来编码私钥。
私钥编码有两种方式:非压缩格式和压缩格式。它们分别对应非压缩公钥和压缩公钥。
非压缩私钥以32字节的私钥前缀0x80为前缀,得到33字节的数据。对这33字节的数据进行SHA256运算,然后对结果再进行一次SHA256运算,取开头4字节一共得到37字节的数据。对这37字节的数据进行Base58编码,生成私钥的WIF(
钱包导入格式)地址。这个字符串总是以5开头。
压缩私钥与非压缩私钥不同的是,使用32字节的私钥前后各添加一个0x80字节前缀和0x01字节后缀,总共34字节。对这34字节的数据进行SHA256运算,取开头4字节作为校验码。将校验码附加到末尾,一共得到38字节的数据。对这38字节的数据进行Base58编码,生成私钥的WIF地址。这个字符串总是以K或L开头。
使用wif库可以实现WIF编码:
const wif = require("wif");
let privateKey = "0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d";
let encoded = wif.encode(
0x80, // 前缀值
Buffer.from(privateKey, "hex"), // 转换为字节
false // 非压缩格式
);
console.log(encoded);
下面的代码展示了如何用比特币JS库压缩私钥:
const bitcoin = require("bitcoinjs-lib");
const BigInteger = require("bigi");
let priv = "0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d",
d = BigInteger.fromBuffer(Buffer.from(priv, "hex"))
let keyPair = new bitcoin.ECPair(d);
console.log(keyPair.toWIF);
目前非压缩的格式已经很少使用了,比特币JS库提供的ECPair总是使用压缩格式的私钥表示。
总而言之,比特币的私钥是256位的整数,通过WIF格式编码私钥可以得到一个带校验的字符串。非压缩格式的WIF地址以5开头,而压缩格式的WIF地址以K或L开头。
热点:区块链 比特币 特币