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 描述 ...