基本定义:P2PKH(Pay-to-Public-Key-Hash)是比特币网络中最常见的地址类型,常被称为标准比特币地址。
P2PKH (Pay-to-Public-Key-Hash) 是比特币网络中最常见的地址类型,常被称为标准比特币地址。生成 P2PKH 地址的过程涉及几个步骤,依赖于公钥和 Hash160 这两个核心概念。
生成比特币地址的第一步是创建一个 私钥,并从私钥中导出 公钥,
secp256k1。私钥 (256位) → 椭圆曲线算法 (secp256k1) → 公钥 (通常是33字节压缩格式)在生成了公钥之后,接下来要对公钥进行两次哈希运算,以生成 Hash160:
这个 160 位的哈希值是地址生成的核心部分。
公钥 → SHA-256 → 哈希1 (32字节)
哈希1 → RIPEMD-160 → Hash160 (20字节)为了区分不同的地址类型,在 Hash160 前面加上一个 版本字节:
0x00,代表这是一个比特币的主网 P2PKH 地址(在测试网中使用的前缀是 0x6F)。P2PKH 地址前缀 = 0x00
P2PKH 地址 = 0x00 + Hash160为了防止地址在传输过程中出错,需要计算并添加一个 校验码:
版本字节 + Hash160 进行两次 SHA-256 哈希运算。Checksum = SHA-256(SHA-256(0x00 + Hash160)) 的前4字节
P2PKH 地址 = 0x00 + Hash160 + 校验码将生成的 0x00 + Hash160 + 校验码 进行 Base58Check 编码,得到最终的 比特币地址。
0、O、I 和 l),确保地址格式更短且适合人类阅读。P2PKH 地址 (Base58Check 编码)这个地址是比特币网络的标准 P2PKH 地址格式。
最终得到的地址是一个以 1 开头的字符串(因为 0x00 版本字节在 Base58 编码中是 1),例如:
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa这个地址是比特币网络的标准 P2PKH 地址格式。
secp256k1 从私钥生成对应的公钥。0x00 作为前缀,代表 P2PKH 地址类型。import * as crypto from 'crypto';
import bs58 from 'bs58';
// 将 16 进制字符串转换为字节数组
function hexStringToBytes(hexStr: string): Buffer {
  return Buffer.from(hexStr, 'hex');
}
// 生成比特币的 P2PKH (Legacy) 地址
export function generateBtcLegacyAddress(publicKeyHex: string): string {
  // 1. 将公钥从 16 进制字符串转换为字节数组
  const publicKeyBytes = hexStringToBytes(publicKeyHex);
  // 2. 进行 SHA-256 哈希
  const sha256Hash = crypto
    .createHash('sha256')
    .update(publicKeyBytes)
    .digest();
  // 3. 进行 RIPEMD-160 哈希
  const ripemd160Hash = crypto
    .createHash('ripemd160')
    .update(sha256Hash)
    .digest();
  // 4. 添加比特币 P2PKH 地址的前缀 0x00
  const version = Buffer.from([0x00]);
  const versionedPayload = Buffer.concat([version, ripemd160Hash]);
  // 5. 进行双重 SHA-256 哈希,用于生成校验和
  const firstSHA = crypto
    .createHash('sha256')
    .update(versionedPayload)
    .digest();
  const secondSHA = crypto.createHash('sha256').update(firstSHA).digest();
  const checksum = secondSHA.slice(0, 4); // 取前 4 个字节作为校验和
  // 6. 将 version, publicKeyHash 和校验和组合在一起
  const fullPayload = Buffer.concat([versionedPayload, checksum]);
  // 7. 使用 Base58 编码
  const address = bs58.encode(fullPayload);
  return address;
}
package utils
import (
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "github.com/btcsuite/btcutil/base58"
    "golang.org/x/crypto/ripemd160"
)
// HexStringToBytes 将 16 进制的字符串转为字节数组
func HexStringToBytes(hexStr string) ([]byte, error) {
    return hex.DecodeString(hexStr)
}
func Generate_btc_legacy_address(publicKeyHex string) (string, error) {
    // 1. 将公钥从16进制字符串转换为字节数组
    publicKeyBytes, err := HexStringToBytes(publicKeyHex)
    if err != nil {
       return "", fmt.Errorf("invalid public key: %v", err)
    }
    // 2. 进行 SHA-256 哈希
    sha256Hash := sha256.New()
    sha256Hash.Write(publicKeyBytes)
    publicKeySHA256 := sha256Hash.Sum(nil)
    // 3. 进行 RIPEMD-160 哈希
    ripemd160Hasher := ripemd160.New()
    ripemd160Hasher.Write(publicKeySHA256)
    publicKeyHash := ripemd160Hasher.Sum(nil)
    // 4. 添加比特币 P2PKH 地址的前缀 0x00
    version := []byte{0x00}
    versionedPayload := append(version, publicKeyHash...)
    // 5. 进行双重 SHA-256 哈希,用于生成校验和
    firstSHA := sha256.Sum256(versionedPayload)
    secondSHA := sha256.Sum256(firstSHA[:]) // 将 [32]byte 转换为切片
    checksumBytes := secondSHA[:4]          // 取前4个字节作为校验和
    // 6. 将 version, publicKeyHash 和校验和组合在一起
    fullPayload := append(versionedPayload, checksumBytes...)
    // 7. 使用 Base58 编码
    address := base58.Encode(fullPayload)
    return address, nil
} 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!