Web3的HD钱包 ----BIP32 分层确定性钱包

  • Dapplink
  • 发布于 2025-04-12 16:58
  • 阅读 6

BIP32(BitcoinImprovementProposal32)定义了一种分层确定性钱包(HierarchicalDeterministicWallet,简称HDWallet),该标准描述了一种树状结构,通过主密钥(MasterKey)生成无限个子密钥(ChildKeys)。

BIP32(Bitcoin Improvement Proposal 32)定义了一种分层确定性钱包(Hierarchical Deterministic Wallet, 简称 HD Wallet),该标准描述了一种树状结构,通过主密钥(Master Key)生成无限个子密钥(Child Keys)。这种方法解决了传统钱包需要频繁备份的问题,并提高了钱包管理的便利性和安全性。

一.BIP32 产生的背景与动机

传统的比特币钱包使用随机生成的私钥,每个地址对应独立的密钥对(私钥、公钥),存在的问题包括:

  • 备份复杂: 每产生一个新地址都需单独备份,容易遗漏。
  • 密钥管理不便: 无法有效组织管理多个地址和账户。
  • 隐私性差: 地址之间没有结构化的关联,隐私保护手段受限。

为了解决以上问题,BIP32 提出了分层确定性钱包方案。

二.HD钱包的核心思想

HD钱包核心是通过 种子(Seed) 生成一个主密钥(Master Key),再通过确定性的派生算法生成树状结构的子密钥,结构清晰,便于管理与备份。

BIP32 描述了两种密钥派生:

  • 私钥派生子私钥 (CKDpriv)

  • 公钥派生子公钥 (CKDpub)

三.BIP32 的派生路径结构

HD 钱包的派生路径类似文件目录结构,格式如下:

ounter(line
m / purpose' / coin_type' / account' / change / address_index
  • m:主密钥(Master Key)。
  • purpose':协议用途,例如 BIP44 中固定为 44'。
  • coin_type':币种编号,例如 Bitcoin 为 0',Ethereum 为 60'。
  • account':账户索引号,用于区分不同账户。
  • change:0 表示外部(接收地址),1 表示找零地址。
  • address_index:地址的序号。

示例(BIP44 标准的比特币地址路径):

ounter(line
m/44'/0'/0'/0/0

四.IP32 密钥派生算法

1.主密钥生成(Master Key Generation)

用户随机生成助记词(Mnemonic),经过 BIP39 生成种子(Seed)。

通过种子使用 HMAC-SHA512 算法派生主密钥:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
Master Key = HMAC-SHA512(key="Bitcoin seed", data=Seed)
HMAC-SHA512 的结果 (512 bits) 被分为两部分:

左 256 bits 为主私钥 (master private key),记作 k。

右 256 bits 为主链码 (chain code),记作 c。
ounter(line
Master Key = (k, c)

链码用于派生子密钥,增强安全性。

2.子密钥派生

子密钥派生包含两种模式:硬化派生和软化派生

2.1.普通派生(软化派生)

可以从公钥或私钥派生子密钥

2.1.1.私钥父密钥-->公钥子密钥

公式

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
I = HMAC-SHA512(key=c_par, data=(K_par || index))
I_L = left 256 bits of I
I_R = right 256 bits of I

child_private_key = (I_L + k_par) mod n
child_chain_code = I_R

算法流程:

  • 函数 N((k, c)) → (K, c) 计算与扩展私钥相对应的扩展公钥(“阉割”版本,因为它消除了签署交易的能力)。
    • 返回的键K是point(k)。
    • 返回的链码c就是传递的链码。
  • 要计算父私钥的公子密钥:
    • N(CKDpriv((k par , c par ), i))(始终有效)。
    • CKDpub(N(k par , c par ), i)(仅适用于非强化子密钥)。
2.1.2.公钥父密钥-->公钥子密钥

公式

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
I = HMAC-SHA512(key=c_par, data=(K_par || index))
I_L = left 256 bits of I
I_R = right 256 bits of I

child_public_key = point(I_L) + K_par
child_chain_code = I_R

说明:

  • c_par 为父链码。
  • K_par 为父公钥(33 字节压缩格式)
  • k_par 为父私钥
  • index 为子密钥索引(0 到 2³¹-1)
  • point() 为椭圆曲线上的公钥点计算
  • mod n 中的 n 是 secp256k1 曲线的阶(curve order)

算法流程

函数 CKDpub((K par , c par ), i) → (K i , c i ) 根据父扩展公钥计算子扩展公钥。该函数仅适用于非强化子密钥。

  • 检查是否 i ≥ 2 31(子密钥是否为硬化密钥)。
    • 如果是(硬化子级):返回失败
    • 如果不是(正常子级):让 I = HMAC-SHA512(Key = c par , Data = ser P (K par ) || ser 32 (i))。
  • 将 I 拆分为两个 32 字节序列,I L和 I R。
  • 返回的子密钥 K i是 point(parse 256 (I L )) + K par。
  • 返回的链码 c i是 I R。
  • 如果解析256 (I L ) ≥ n 或 K i是无穷远点,则生成的密钥无效,并且应该继续处理 i 的下一个值。

优点:

  • 支持公钥派生,方便应用。

缺点:

  • 公钥泄漏时,可能导致派生密钥暴露风险。

2.2.硬化派生

  • 仅支持通过私钥派生子密钥,不支持公钥派生。
  • 公式(硬化派生):
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
I = HMAC-SHA512(key=c_par, data=(0x00 || k_par || index))
I_L = left 256 bits of I
I_R = right 256 bits of I

child_private_key = (I_L + k_par) mod n
child_chain_code = I_R

私钥父密钥 → 公钥子密钥算法流程

  • 函数 N((k, c)) → (K, c) 计算与扩展私钥相对应的扩展公钥(“阉割”版本,因为它消除了签署交易的能力)。
    • 返回的键K是point(k)。
    • 返回的链码c就是传递的链码。
  • 要计算父私钥的公子密钥:
    • N(CKDpriv((k par , c par ), i))(始终有效)。
    • CKDpub(N(k par , c par ), i)(仅适用于非强化子密钥)。
  • 索引号 ≥ 2³¹(标记硬化路径,如 0')。
  • 优点:提高安全性,即使公钥泄漏也不会暴露其他子密钥。
  • 缺点:仅能私钥派生,不方便生成公共地址。

推荐实践: 硬化派生用于敏感用途,例如账户级别的密钥派生。

五.HD 钱包的优点

  • 易于备份:用户仅需备份种子或主密钥,即可恢复所有子地址。
  • 安全性提升:硬化派生机制提高安全性,防止公钥泄露引起密钥泄露。
  • 隐私保护:每次交易都可使用新的地址,有效保护用户隐私。
  • 管理方便:层次化的组织方式便于账户管理与权限分级。

六.常用的相关标准

  • BIP39:定义助记词生成方式及种子生成
  • BIP44:在 BIP32 基础上,定义了清晰的账户和地址结构,广泛应用于多币种钱包
  • BIP49:基于 P2SH-P2WPKH 地址结构(兼容隔离见证)
  • BIP84:原生隔离见证(P2WPKH)地址结构

七.示例与代码实战

  • 生成种子 → 主密钥 → 子密钥 → 地址流程:
ounter(line
助记词 → 种子 → Master Key → 子密钥 → 地址
  • 举例:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
助记词:"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"
↓
种子(seed)
↓
主密钥(m)
↓
子密钥(m/44'/0'/0'/0/0)
↓
地址:"1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA"

1.代码实战

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
const bip39 = require('bip39');
const bip32 = require('bip32');
const bitcoin = require('bitcoinjs-lib');

// 生成主密钥function generateMasterNode() { 
    const mnemonic = bip39.generateMnemonic(); 
    const seed = bip39.mnemonicToSeedSync(mnemonic); 
    const root = bip32.fromSeed(seed); 
    console.log('助记词:', mnemonic); 
    console.log('种子:', seed.toString('hex')); 
    return root;
}

// 非硬化派生
function deriveNonHardened(root, path) { 
    const node = root.derivePath(path);
    console.log(`\n非硬化路径 ${path}`); 
    console.log('子私钥 (WIF):', node.toWIF()); 
    console.log('子公钥:', node.publicKey.toString('hex')); 
    console.log('地址:', bitcoin.payments.p2pkh({ pubkey: node.publicKey }).address);
}

// 硬化派生
function deriveHardened(root, path) { 
    const node = root.derivePath(path); 
    console.log(`\n硬化路径 ${path}`);  
    console.log('子私钥 (WIF):', node.toWIF()); 
    console.log('子公钥:', node.publicKey.toString('hex')); 
    console.log('地址:', bitcoin.payments.p2pkh({ pubkey: node.publicKey }).address);
}

// 主函数
function main() {  
    const root = generateMasterNode();

  // 非硬化路径  
  deriveNonHardened(root, "m/0/1/2");

  // 硬化路径 
  deriveHardened(root, "m/0'/1'/2'");
}

main();

八.总结

BIP32 提供了一种强大的密钥管理结构,通过分层确定性设计,极大提升了加密货币钱包的安全性、便利性和易用性,现已成为加密货币钱包设计的主流标准。

掌握 BIP32 及相关标准对理解钱包底层原理、区块链产品开发有非常重要的意义。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Dapplink
Dapplink
0xBdcb...f214
首个模块化、可组合的Layer3协议。