主页 > imtoken手机钱包 > 比特币私钥贴吧 如果你看完有收获,可以邀请作者在支付宝上喝咖啡

比特币私钥贴吧 如果你看完有收获,可以邀请作者在支付宝上喝咖啡

imtoken手机钱包 2023-01-18 17:57:27

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

在JavaScript中,内置的Number类型使用56位来表示整数和浮点数,能表示的最大整数只有9007199254740991。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字节的数据:

0x80           256bit             check
┌─┬──────────────────────────────┬─────┐
│1│              32              │  4  │
└─┴──────────────────────────────┴─────┘

计算校验码很简单,对它进行两次SHA256,取前4个字节作为校验码。

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

uncompressed-wif

可以使用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个获取字节数据:

0x80           256bit           0x01 check
┌─┬──────────────────────────────┬─┬─────┐
│1│              32              │1│  4  │
└─┴──────────────────────────────┴─┴─────┘

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

p>

compressed-wif

通过代码压缩格式的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());

总结

bit 硬币的私钥本质上是一个 256 位整数。将私钥编码成WIF格式可以得到带有校验和的字符串。

未压缩格式的 WIF 是一个以 5 开头的字符串。

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