比特币地址的生成与格式解析

我们先带着如下问题开始我们的编程工作:

  1. 私钥、公钥和地址有什么关系?

  2. 什么是WIF?

  3. Base58 和 Bech32 是什么?为什么有不同的编码方式?

  4. 不同格式的地址有什么区别?它们的长度为什么不一样?

想要产生私钥、公钥和地址,其实很简单,一句代码就可以,我们先动手运行如下代码:

使用python的bitcoinlib库编程

from bitcoinlib.keys import Key

# 生成比特币钱包
key = Key()

# 生成私钥
private_key_hex = key.private_hex  # 32 字节(256-bit)
private_key_wif = key.wif()  # Base58Check 编码

# 生成公钥
public_key_compressed = key.public_hex  # 33 字节,压缩格式
public_key_uncompressed = key.public_uncompressed_hex  # 65 字节,未压缩格式

# 生成不同格式的比特币地址
legacy_address = key.address()  # P2PKH (Base58, 1...)
segwit_native_address = key.address(encoding='bech32')  # P2WPKH (Bech32, bc1q...)
segwit_p2sh_address = key.address(encoding='base58', script_type='p2sh')  # P2SH-P2WPKH (3...)
taproot_address = key.address(script_type='p2tr')  # P2TR (Bech32m, bc1p...)

# 打印结果
print("===== 比特币钱包信息 =====")
print(f"私钥(HEX): {private_key_hex}")
print(f"私钥(WIF): {private_key_wif}")
print(f"公钥(压缩): {public_key_compressed}")
print(f"公钥(未压缩): {public_key_uncompressed}")
print("\n地址类型:")
print(f"Legacy (P2PKH, Base58): {legacy_address}")
print(f"Segwit Native (P2WPKH, Bech32): {segwit_native_address}")
print(f"Segwit P2SH (P2SH-P2WPKH, Base58): {segwit_p2sh_address}")
print(f"Taproot (P2TR, Bech32m): {taproot_address}"

我这次的运行结果如下:

===== 比特币钱包信息 =====
私钥(HEX): e9873d79c6d87dc0fb6a5778633389dfa5c32fa27f99b5199abf2f9848ee0289
私钥(WIF): L1aW4aubDFB7yfras2S1mN3bqg9w3KmCPSM3Qh4rQG9E1e84n5Bd
公钥(压缩): 0250be5fc44ec580c387bf45df275aaa8b27e2d7716af31f10eeed357d126bb4d3
公钥(未压缩): 0450be5fc44ec580c387bf45df275aaa8b27e2d7716af31f10eeed357d126bb4d3...

地址类型:
Legacy (P2PKH, Base58): 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
Segwit Native (P2WPKH, Bech32): bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080
Segwit P2SH (P2SH-P2WPKH, Base58): 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
Taproot (P2TR, Bech32m): bc1plz0h3rlj2zvn88pgywqtr9k3df3p75p3ltuxh0

大家一定要动手运行一下。

看到这里,我们来解释下之前的疑问:

1、比特币的私钥、公钥和地址的关系是什么?

可以简单理解如下:

  • 私钥:随机生成的 256 位(32 字节)数据,用于签名交易。比如e9873d79c6d87dc0fb6a5778633389dfa5c32fa27f99b5199abf2f9848ee0289。

数一数:e9873d79c6d87dc0fb6a5778633389dfa5c32fa27f99b5199abf2f9848ee0289有多少字符?

没错64个字符,也就是64个HEX(16进制)字符。请记住:每4位(四个bit)就可以压缩为一个HEX字符;每两个HEX就可以压缩为一个字节(Bite)。私钥就是256位,或64个HEX字符,或者32字节。不同的进制,也就是一个占位符能包含的信息量。

什么是WIF?

比特币私钥一般不会直接用 64 HEX 形式,而是用 WIF(Base58Check 编码) 进行格式化,方便存储和导入钱包,虽然我个人也没有觉得方便了多少。

WIF 格式转换过程, 看不懂可以直接忽略:

1.添加版本前缀

•主网(Mainnet): 0x80

•测试网(Testnet): 0xEF

例如:

80e9873d79c6d87dc0fb6a5778633389dfa5c32fa27f99b5199abf2f9848ee0289

2.计算两次 SHA-256

•SHA256(SHA256(80e9...0289))

•取前 4 字节 作为校验和

结果是一个 51 或 52 个字符的字符串,比如

L1aW4aubDFB7yfras2S1mN3bqg9w3KmCPSM3Qh4rQG9E1e84n5Bd

•L 开头的 WIF 表示主网压缩私钥

•K 开头的 WIF 表示主网未压缩私钥

•c 开头的 WIF 表示测试网私钥

总结,WIF 只是比特币私钥的 Base58Check 编码,方便存储和导入钱包。

  • 公钥:通过椭圆曲线加密(secp256k1)从私钥推导出。公钥有压缩和压缩之分,但我们碰到的基本都是压缩公钥,33个字节,比如0250be5fc44ec580c387bf45df275aaa8b27e2d7716af31f10eeed357d126bb4d3(算一下多少个字符?)

  • 地址:公钥经过哈希处理(SHA-256 + RIPEMD-160)并进行不同格式编码,生成可用于交易的地址。

SHA-256(Secure Hash Algorithm 256-bit)是一种广泛应用的加密哈希函数,会将公钥转换为 256 位(32 字节)的哈希值。

RIPEMD-160(RACE Integrity Primitives Evaluation Message Digest 160-bit)是一种更短的哈希算法,它会进一步压缩 SHA-256 的输出,生成 160 位(20 字节)的哈希值,作为公钥哈希(PubKeyHash,记住这个单词)。

如何进行编码,请见后面我们介绍base58和bech32。

3、进制与编码:Base58 和 Bech32

比特币的编码格式主要有 Base58Check 和 Bech32:

  • Base58Check:用于 P2PKH 和 P2SH 地址,避免混淆字符(0、O、I、l),提高可读性。

  • Bech32:用于 SegWit 地址(P2WPKH 和 P2TR),更高效,带错误校验机制。

4、比特币地址类型介绍

  1. P2PKH(Pay-to-PubKey Hash)

  • 经典的比特币地址格式。

  • 基于公钥哈希(RIPEMD-160 + SHA-256)。

  • 使用 Base58Check 编码,地址以 1 开头。

  • 示例地址:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

比特币地址格式,P2PKH(Pay-to-Public-Key-Hash),字面意思是把钱支付到公钥对应的哈希,但其实更精确的概念不仅仅是直接支付给公钥哈希本身,而是支付给一个包含公钥哈希的锁定脚本(scriptPubKey,记住这个单词)。这在以后我们讲UTXO模型的时候很详细的讲。

  1. P2SH(Pay-to-Script Hash)

  • 用于多重签名地址和嵌套的 SegWit 地址。Pay-to-Script Hash 顾名思义,把钱打到一个脚本哈希。这个脚本script,常常说的是一个多签(Multisig)的脚本。

  • 使用 Base58Check 编码,地址以 3 开头。

  • 示例地址:3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy

  1. P2WPKH(Pay-to-Witness PubKey Hash)

  • 隔离见证(SegWit)地址格式。SegWit和Taproot是我们本书要详细介绍的技术。

  • 使用 Bech32 编码,地址以 bc1q 开头。

  • 比 P2PKH 交易效率更高,手续费更低。

  • 示例地址:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080

  1. P2TR(Pay-to-Taproot)

  • 采用 Taproot 技术,进一步提升隐私性和效率。

  • 使用 Bech32m 编码,地址以 bc1p 开头。

  • 适用于复杂的智能合约和多签方案。

  • 示例地址:bc1plz0h3rlj2zvn88pgywqtr9k3df3p75p3ltuxh0

地址格式和字节数

地址类型

编码格式

原始数据大小

最终地址长度

前缀

P2PKH

Base58Check

25 字节

34 字符左右

1...

P2SH

Base58Check

25 字节

34 字符左右

3...

P2WPKH

Bech32

21 字节

42~46 字符

bc1q...

P2TR

Bech32m

33 字节

58~62 字符

bc1p...

总结

  1. 私钥(HEX 32字节)WIF(Base58Check 编码) 方便存储。

  2. 公钥(33/65字节)比特币地址(Base58 / Bech32 编码) 用于收款。

  3. SegWit(Bech32)和Taproot(Bech32m) 具有更好的安全性和效率,逐步替代 Base58 地址。

Last updated