主页 > imtoken钱包官方下载最新版 > 跟着老廖(廖雪峰)学习区块链(5)教程:公钥和地址)

跟着老廖(廖雪峰)学习区块链(5)教程:公钥和地址)

公钥

比特币的公钥是根据私钥计算出来的。

私钥本质上是一个 256 位整数,用 k 表示。根据比特币采用的ECDSA算法,可以推导出两个256位整数,记为(x,y),这两个256位整数就是未压缩格式的公钥。

由于ECC曲线的特性,y实际上可以从未压缩格式的公钥(x,y)的x中计算出来,但是需要知道y的奇偶性。因此怎么知道自己的比特币地址,x' 可以从 (x, y) 计算出来,作为压缩格式的公钥。

压缩格式的公钥实际上只存储了一个256位的整数x,但是需要根据y的奇偶性给x加02或者03前缀,y为偶数时加02,否则加03,这样就得到了1+32 = 33 字节压缩格式的公钥数据,表示为 x'。

注意压缩格式的公钥和非压缩格式的公钥可以相互转换,但私钥不能逆推。

很少使用未压缩的公钥,因为未压缩的公钥签名脚本数据会更长。

让我们看看如何从私钥推导出公钥:

const bitcoin = require('bitcoinjs-lib');
let
    wif = 'KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617',
    ecPair = bitcoin.ECPair.fromWIF(wif); // 导入私钥
// 计算公钥:
let pubKey = ecPair.getPublicKeyBuffer(); // 返回Buffer对象
console.log(pubKey.toString('hex')); // 02或03开头的压缩公钥

构造好ECPair对象后,可以通过getPublicKeyBuffer()将公钥数据作为Buffer对象返回。

地址

需要注意的是,比特币的地址不是公钥,而是公钥的hash,即可以从公钥推导出地址,但不能从地址推导出公钥,因为hash函数是单向函数。

以压缩格式的公钥为例,从公钥计算地址的方法是先对1+32=33字节的公钥数据进行Hash160(即先计算SHA256,再计算RipeMD16< @0),得到20个字节的hash。然后,加上0x00前缀,得到1+20=21个字节的数据,然后计算4个字节的校验码,放在一起,一共得到1 +20+4=25 字节数据:

跟老廖(廖雪峰)学习区块链(5)教程:公钥和地址

对上述25字节数据进行Base58编码,得到一个始终以1开头的字符串,即比特币地址。整个过程如下:

跟老廖(廖雪峰)学习区块链(5)教程:公钥和地址

使用 JavaScript 对地址的公钥编码如下:

const bitcoin = require('bitcoinjs-lib');
let
    publicKey = '02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c',
    ecPair = bitcoin.ECPair.fromPublicKeyBuffer(Buffer.from(publicKey, 'hex')); // 导入公钥
// 计算地址:
let address = ecPair.getAddress();
console.log(address); // 1开头的地址

计算地址时,不需要知道私钥,可以直接从公钥计算地址,即通过ECPair.fromPublicKeyBuffer构造一个没有私钥的ECPair来计算地址。

需要注意的是,未压缩格式的公钥和压缩格式的公钥哈希得到的地址都是以1开头的,因此无法从地址上区分是使用压缩格式还是未压缩格式本身。公钥。

以 1 开头的字符串地址是比特币接收地址,可以安全地向任何人披露。

仅提供地址不会使其他人知道公钥。一般来说,公开公钥不存在安全风险。事实上怎么知道自己的比特币地址,如果某个地址上有相应的资金,则需要提供公钥才能使用该资金。如果地址的资金至少被使用过一次,则地址的公钥实际上是公开的。

私钥、公钥和地址的推导关系如下:

跟老廖(廖雪峰)学习区块链(5)教程:公钥和地址

概括

比特币的公钥是根据私钥通过 ECDSA 算法计算出来的。

比特币的地址是公钥哈希的代码,而不是公钥本身。地址可以从公钥中推导出来。

不能从地址推导出公钥,也不能从公钥推导出私钥。

要在线运行代码,请在浏览器中查看以下链接