BIP32 钱包私钥分层推导方案

钱包是一个私钥的容器,我们可以生成一堆私钥,因为一个人也有很多账号的需求,可以更好保护隐私,但是管理每个私钥就特别麻烦。为了解决这种麻烦,就有了 BIP32 提议: 根据一个随机数种子通过分层确定性推导的方式得到 n 个私钥。因此保存的时候,只需要保存一个种子就可以,私钥可以推导出。

BIP32 就是为了避免管理大量私钥提出的分层推导方案。

 

补充说明: BIP,即Bitcoin Improvement Proposals 比特币改进建议,bip32 是第 32 个改进建议。

BIP32 提案的名字是:Hierarchical Deterministic Wallets,分层推导钱包,也就是我们所说的 HD 钱包。

1. BIP32 推导过程

我们来分析下这个分层推导的过程,第一步推导主秘钥的过程:

根种子输入到 HMAC-SHA512 算法中就可以得到一个可用来创造主私钥 (m) 和 一个主链编码( a master chain code) 这一步生成的秘钥(由私钥或公钥)及主链编码再加上一个索引号,将作为 HMAC-SHA512 算法的输入继续衍生出下一层的私钥及链编码,如下图:

衍生推导的方案其实有两个:一个用父私钥推导(称为强化衍生方程),一个用父公钥推导。同时为了区分这两种不同的衍生,在索引号也进行了区分,索引号小于 2^31 用于常规衍生,而 2^31 到 2^32-1 之间用于强化衍生,为了方便表示索引号 i’,表示 2^31+i。

因此增加索引(水平扩展)及 通过子秘钥向下一层(深度扩展)可以无限生成私钥。

注意, 这个推导过程是确定(相同的输入,总是有相同的输出)也是单向的,子密钥不能推导出同层级的兄弟密钥,也不能推出父密钥。如果没有子链码也不能推导出孙密钥。现在我们已经对分层推导有了认识。

非强化衍生key父公钥推导子公钥的安全问题:

访问扩展公共钥匙并不能得到访问子私人密钥的途径。但是,因为扩展公共钥匙包含有链码,如果子私钥被知道或者被泄漏的话,链码就可以被用来衍生所有的其他子私钥。一个简单地泄露的私钥以及一个母链码,可以暴露所有的子密钥。更糟糕的是,子私钥与母链码可以用来推断母私钥。

解决办法:为了避免了推到出主钥匙,主钥匙所衍生的第一层级的子钥匙最好使用强化衍生。

2. BIP32 示例代码

package main

import (
  "github.com/tyler-smith/go-bip32"
  "fmt"
  "log"
)

// Example address creation for a fictitious company ComputerVoice Inc. where
// each department has their own wallet to manage
func main(){
  // Generate a seed to determine all keys from.
  // This should be persisted, backed up, and secured
  seed, err := bip32.NewSeed()
  if err != nil {
    log.Fatalln("Error generating seed:", err)
  }

  // Create master private key from seed
  computerVoiceMasterKey, _ := bip32.NewMasterKey(seed)

  // Map departments to keys
  // There is a very small chance a given child index is invalid
  // If so your real program should handle this by skipping the index
  departmentKeys := map[string]*bip32.Key{}
  departmentKeys["Sales"], _ = computerVoiceMasterKey.NewChildKey(0)
  departmentKeys["Marketing"], _ = computerVoiceMasterKey.NewChildKey(1)
  departmentKeys["Engineering"], _ = computerVoiceMasterKey.NewChildKey(2)
  departmentKeys["Customer Support"], _ = computerVoiceMasterKey.NewChildKey(3)

  // Create public keys for record keeping, auditors, payroll, etc
  departmentAuditKeys := map[string]*bip32.Key{}
  departmentAuditKeys["Sales"] = departmentKeys["Sales"].PublicKey()
  departmentAuditKeys["Marketing"] = departmentKeys["Marketing"].PublicKey()
  departmentAuditKeys["Engineering"] = departmentKeys["Engineering"].PublicKey()
  departmentAuditKeys["Customer Support"] = departmentKeys["Customer Support"].PublicKey()

  // Print public keys
  for department, pubKey := range departmentAuditKeys {
    fmt.Println(department, pubKey)
  }
}

BIP: 39层级:应用层链接:https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki创建时间:2013-09-101. 摘要BIP39 描述 ...