主页 > imtoken钱包官网客服 > 《精通比特币》解读第4章——密钥、地址

《精通比特币》解读第4章——密钥、地址

imtoken钱包官网客服 2023-09-20 05:12:05

本章主要讲私钥、公钥、比特币地址

私钥、公钥和比特币地址的关系如下图所示:

这里写图片描述

私钥

什么是私钥:私钥是一个随机生成的256位数字

私钥是如何生成的:生成比特币私钥本质上与“选择一个介于 1 和 2^256 之间的数字”是一样的。 只要选择的结果不可预测或不可重复,选择数字的确切方法并不重要。 可以用硬币、铅笔和纸随机生成你的私钥:抛一枚硬币256次,用纸笔记录正反面转换成0和1,就可以使用随机的256位二进制数作为比特币钱包的私钥。 比特币软件使用操作系统底层的随机数生成器来生成 256 位的熵。

私钥的作用:私钥可以进一步生成公钥。 私钥控制相应比特币地址中的所有资金。

私钥空间大小:2^256,约1.158 * 10^77

使用 Bitcoin Core 客户端生成新密钥:

使用获取新地址命令。 为了安全起见,命令运行后只显示生成的公钥,不显示私钥。 如果想让bitcoind显示私钥,可以使用dumpprivkey命令。

$ bitcoin-cli getnewaddress
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
$ bitcoin-cli dumpprivkey 1J7mdg5rbQyUHENYdx39WVWK7fsL
KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ

公钥

什么是公钥:公钥是由私钥生成的一串数字和字母。

公钥可以通过椭圆曲线乘法从私钥计算出来,这是一个不可逆的过程:K = k * G 。 其中 k 是私钥,G 是称为生成点的常数点,K 是生成的公钥。 它的逆运算比特币私钥格式转换器,被称为“求离散对数”——知道公钥K来求私钥k——是非常困难的,就像试图测试k的所有可能值一样,也就是蛮力搜索。

比特币使用特殊的椭圆曲线和一系列由 secp256k1 标准定义的数学常数。

生成公钥:

从随机生成的私钥k开始,我们将其与曲线上预定的生成点G相乘得到曲线上的另一个点,即对应的公钥K。生成点是secp256k1标准的一部分,是相同的对于所有比特币密钥。

{K = k * G}

其中k为私钥,G为生成点,曲线上的生成点K为公钥。 因为所有比特币用户的生成点都是相同的,私钥 k 乘以 G 将产生相同的公钥 K。

因为里面的数学是单向的,私钥可以转换为公钥,但是公钥不能转换回私钥。

比特币地址

什么是比特币地址:比特币地址是由公钥生成的一串数字和字母,以数字“1”开头。

比特币钱包私钥论坛_比特币私钥格式转换器_比特币私钥公钥签名

如:1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy

比特币地址可以代表公钥/私钥对的所有者

如何生成比特币地址:比特币地址可以通过单向密码哈希算法从公钥中获得。 这些算法是安全哈希算法 (SHA) 和 RACE Integrity Primitives Evaluation Message Digest (RIPEMD),特别是 SHA256 和 RIPEMD160。

以公钥K为输入,计算其SHA256哈希值,并根据结果计算RIPEMD160哈希值,得到一个长度为160位(20字节)的数:

A = RIPEMD160(SHA256(K))

式中,K为公钥,A为生成的比特币地址。

通常,用户看到的比特币地址是经过“Base58Check”编码的。 这种编码使用了58个字符(一种Base58数字系统)和校验码,提高了可读性,避免了歧义,有效地防止了地址在转录和打字时的错误。

下图描述了如何从公钥生成比特币地址:

这里写图片描述

Base58和Base58Check编码

Base58:Base64中不包含0(数字0)、O(大写字母o)、l(小写字母L)、I(大写字母i)和“+”、“/”两个字符

Base58Check:是比特币常用的一种Base58编码格式,内置了一种错误校验编码(checksum),可以防止写入错误和转录错误。

功能:当使用Base58check编码时,解码软件会计算数据的校验和,并与编码中包含的校验和进行比较。 如果两者不匹配,就会出错,Base58Check数据无效。 错误的比特币地址不会被钱包软件认为是有效地址,否则这种错误会造成资金的损失。

base58check编码过程:

1、首先我们需要给数据添加一个前缀,叫做“version byte”,用来标识编码数据的类型。

2、接下来计算“double hash”校验和,也就是对前面的结果(前缀和数据)运行两次SHA256哈希算法:

校验和 = SHA256(SHA256(前缀+数据))

在生成的 32 字节长哈希(两次哈希操作)中,我们只取前 4 个字节。 这 4 个字节用作检查错误的代码或校验和。 数据后将添加校验和。

3、结果由前缀、数据、校验和三部分组成。 然后如前所述使用 Base58 对该结果进行编码。

下图描述了Base58Check编码的过程:

这里写图片描述

在比特币中,大部分需要展示给用户的数据都是使用Base58Check编码的,可以实现数据压缩、可读性和错误校验。

Base58Check 编码中的版本前缀用于创建易于区分的格式。 版本前缀编码后,一些特殊的字符可以让用户轻松识别编码数据的类型以及如何使用。 显示了一些版本前缀及其对应的 Base58 编码字符:

这里写图片描述

回顾一下比特币地址生成的完整过程,从私钥,到公钥(椭圆曲线上的一个点),再到二次哈希地址,再到最后的Base58Check编码。 以下 C++ 代码详细显示了从私钥到 Base58Check 编码的比特币地址的步骤。 代码使用了“3.3 其他客户端、数据库和工具包”一节中介绍的libbitcoin库,实现了一些辅助功能:

比特币私钥格式转换器_比特币私钥公钥签名_比特币钱包私钥论坛

#include <bitcoin/bitcoin.hpp>
int main()
{
// Private secret key.
bc::ec_secret secret;
bool success = bc::decode_base16(secret,
"038109007313a5807b2eccc082c8c3fbb988a973cacf1a7df9ce725c31b14776");
assert(success);
// Get public key.
bc::ec_point public_key = bc::secret_to_public_key(secret);
std::cout << "Public key: " << bc::encode_hex(public_key) << std::endl;
// Create Bitcoin address.
// Normally you can use:
// bc::payment_address payaddr;
// bc::set_public_key(payaddr, public_key);
// const std::string address = payaddr.encoded();
// Compute hash of public key for P2PKH address.
const bc::short_hash hash = bc::bitcoin_short_hash(public_key);
bc::data_chunk unencoded_address;
// Reserve 25 bytes
// [ version:1 ]
// [ hash:20 ]
// [ checksum:4 ]
unencoded_address.reserve(25);
// Version byte, 0 is normal BTC address (P2PKH).

比特币钱包私钥论坛_比特币私钥公钥签名_比特币私钥格式转换器

unencoded_address.push_back(0); // Hash data bc::extend_data(unencoded_address, hash); // Checksum is computed by hashing data, and adding 4 bytes from hash. bc::append_checksum(unencoded_address); // Finally we must encode the result in Bitcoin's base58 encoding. assert(unencoded_address.size() == 25); const std::string address = bc::encode_base58(unencoded_address); std::cout << "Address: " << address << std::endl; return 0; }

编译并运行地址代码:

# Compile the addr.cpp code
$ g++ -o addr addr.cpp $(pkg-config --cflags --libs libbitcoin)
# Run the addr executable
$ ./addr
Public key: 0202a406624211f2abbdc68da3df929f938c3399dd79fac1b51b0e4ad1d26a47aa
Address: 1PRTTaJesdNovgne6Ehcdu1fpEdX7913CK

密钥格式

公钥和私钥都可以采用多种格式。 一个密钥经过不同的格式编码后,虽然结果可能看起来不同,但它们都是由同一个数字编码的。 这些不同的编码格式主要是为了方便密钥的使用和识别而不会出错。

私钥格式:

私钥可以用多种不同的格式表示,所有格式都对应于相同的 256 位数字。

下表显示了私钥的三种常见格式:

这里写图片描述

不同的场景使用不同的格式。 十六进制和原始二进制格式由软件内部使用,很少向用户显示。 WIF 格式用于钱包之间密钥的输入和输出,也用于表示私钥的二维码(条形码)。

比特币私钥格式转换器_比特币私钥公钥签名_比特币钱包私钥论坛

下表显示了以三种格式生成的私钥:

这里写图片描述

从 Base58Check 解码

使用 Bitcoin Explorer 命令解码 Base58Check 格式

1、使用base58check-decode命令对解压后的密钥进行解码:

$ bx base58check-decode 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn
wrapper
{
checksum 4286807748
payload 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd
version 128
}

结果包含作为有效负载的密钥、WIF 版本前缀 128 和校验和。

2.使用base58check-decode命令解码压缩密钥:

$ bx base58check-decode KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ
wrapper
{
checksum 2339607926
payload 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd01
version 128
}

注意压缩密钥的“payload”后缀为01,表示导出的公钥是要压缩的。

将十六进制密钥转换为 Base58Check 编码

使用比特币浏览器的 base58check-encode 命令

bx base58check-encode 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd --version 128

比特币钱包私钥论坛_比特币私钥公钥签名_比特币私钥格式转换器

5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn

将十六进制密钥(压缩格式密钥)转换为 Base58Check 编码

需要在十六进制私钥后面加上后缀01,然后使用同上方法:

$ bx base58check-encode 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd01 --version 128
KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ

生成的WIF压缩格式的私钥以字母“K”开头,表示编码后的私钥后缀为“01”,此私钥只能用于生成压缩格式的公钥(见“压缩格式化公钥”部分)。

公钥格式

公钥也可以用多种不同的格式表示,通常是未压缩或压缩的公钥形式。

我们从上一篇文章中知道,公钥是椭圆曲线上的一个点,由一对坐标(x,y)组成。 公钥通常由前缀 04 后跟两个 256 位数字表示。 其中一个 256 位数字是公钥的 x 坐标,另一个 256 位数字是 y 坐标。 前缀04用于区分非压缩格式公钥,压缩格式公钥以02或03开头。

未压缩格式的公钥:

下面是上面私钥生成的公钥,其坐标x和y如下:

x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

下面是表示为 520 位数字(130 个十六进制数字)的相同公钥。 这个 520 位数字以前缀 04 开头,后跟 x 和 y 坐标,格式为 04 xy:

K = 04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE 52DDFE2E505BDB

压缩格式公钥:

未压缩的公钥以 04 为前缀,而压缩的公钥以 02 或 03 为前缀。需要这两个不同前缀的原因是:

因为椭圆曲线加密公式左边是y2,也就是说y的解来自一个平方根,可能是正数也可能是负数。 更形象地说,y 坐标可以高于或低于 x 坐标。 当我们用二元运算在素数p阶有限域上计算椭圆曲线时,y坐标可能是奇数也可能是偶数比特币私钥格式转换器,对应前面提到的y值的正负号。 因此,为了区分y坐标的两种可能取值,我们在生成压缩格式公钥时,如果y为偶数则使用02作为前缀,如果y为奇数则使用03作为前缀。 这样就可以根据公钥中给定的x值正确推导出对应的y坐标,从而将公钥解压成椭圆曲线上的一个完整的点坐标。

下图说明了公钥压缩:

这里写图片描述

下面是上一节生成的公钥,采用264位(66位十六进制数字)压缩格式公钥格式,其中前缀03表示y坐标为奇数:

K = 03F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

压缩格式的私钥:

其实“压缩格式私钥”是一个误导性的名称,私钥是未压缩的,不能压缩。 “压缩私钥”实际上只是指“用于生成压缩格式公钥的私钥”,而“未压缩格式私钥”用于表示“用于生成未压缩格式公钥的私钥”。

下图显示了相同的私钥,但格式不同:

这里写图片描述