如何在Python中从种子生成比特币密钥/地址?

时间:2019-01-15 16:06:47

标签: python cryptography bitcoin

我正在尝试根据BIP0039从助记符创建一组公用/专用密钥。我正在使用Python。

这是我到目前为止的代码:

from mnemonic import Mnemonic
mnemon = Mnemonic('english')
words = mnemon.generate(256)
mnemon.check(words)
seed = mnemon.to_seed(words)

在BIP0039中,声明您应该能够获得带有种子的Key,但是我无法使用bip32utils在Python中弄清楚它。有没有人举过一个例子,说明如何使用bip32utils将种子转换成私钥/公钥及其各自的地址?

1 个答案:

答案 0 :(得分:1)

从助记符生成种子已经在发布的代码中实现了。

根密钥是从种子派生的:

root_key = bip32utils.BIP32Key.fromEntropy(seed)

对于 BIP32,子密钥是通过以下方式创建的:

child_key = root_key.ChildKey(0).ChildKey(0)

对于 BIP44:

child_key = root_key.ChildKey(44 + bip32utils.BIP32_HARDEN).ChildKey(0 + bip32utils.BIP32_HARDEN).ChildKey(0 + bip32utils.BIP32_HARDEN).ChildKey(0).ChildKey(0) 

BIP32Key 类封装了密钥,并提供了不同的方法来检索不同格式的密钥。


BIP32 示例:

from mnemonic import Mnemonic
import bip32utils

mnemon = Mnemonic('english')
#words = mnemon.generate(256)
#print(words)
#mnemon.check(words)
#seed = mnemon.to_seed(words)
seed = mnemon.to_seed(b'lucky labor rally law toss orange weasel try surge meadow type crumble proud slide century')
print(f'BIP39 Seed: {seed.hex()}\n')

root_key = bip32utils.BIP32Key.fromEntropy(seed)
root_address = root_key.Address()
root_public_hex = root_key.PublicKey().hex()
root_private_wif = root_key.WalletImportFormat()
print('Root key:')
print(f'\tAddress: {root_address}')
print(f'\tPublic : {root_public_hex}')
print(f'\tPrivate: {root_private_wif}\n')

child_key = root_key.ChildKey(0).ChildKey(0)
child_address = child_key.Address()
child_public_hex = child_key.PublicKey().hex()
child_private_wif = child_key.WalletImportFormat()
print('Child key m/0/0:')
print(f'\tAddress: {child_address}')
print(f'\tPublic : {child_public_hex}')
print(f'\tPrivate: {child_private_wif}\n')

产生输出:

BIP39 Seed: 487a440fb26cb376168b6b88a2e46699cb9967bdc4a107fab571f6fdeaab02ea95d149073b3319735c5eace5acafd362edd1ad4c3ac3f655aaa6468973999500

Root key:
    Address: 15Zpz6hJkSkAiw1A5Sm9UoemCVBCuW1SSP
    Public : 036830d1cbcecf9e01ce1ddb154ccb754a6a765d06b3b48dced926861e03bd9485
    Private: KzKjSsprRaWBfVy3oPNwPJBAzVxLXU5AAT5Xe9EJh5pJjpJAqP7q

Child key m/0/0:
    Address: 1AP5U7iDUrvH8B1m1qiarbkA31Ux7jX8YF
    Public : 03a78bb2b1fb86280b4091e5cdffc5d8c87430f5c0988e84a7c5d972bb3f1a1b93
    Private: L47DQmmwwc88oZLPmyZr7CQWn1RzayBmH6gSpnFoMRCCTsR5yRpN

这可以使用网站 https://iancoleman.io/bip39/#english 进行验证,方法是将上述示例中使用的助记符输入 BIP39 助记符 字段并选择 BIP32 作为派生路径。


可以使用 BIP32Key#dump() 方法以不同格式转储密钥,例如:

root_key.dump()

提供以下输出:

* Identifier
  * (hex):       b'3215de8b72f8c407682a6e9334ccd11ae17b1f9c'
  * (fpr):       b'3215de8b'
  * (main addr): 15Zpz6hJkSkAiw1A5Sm9UoemCVBCuW1SSP
* Secret key
  * (hex):       5c9c29e08d1ee9d3c8295ba2a931a9f0166e4282cc01702549664736a16b3a89
  * (wif):       KzKjSsprRaWBfVy3oPNwPJBAzVxLXU5AAT5Xe9EJh5pJjpJAqP7q
* Public key
  * (hex):       b'036830d1cbcecf9e01ce1ddb154ccb754a6a765d06b3b48dced926861e03bd9485'
* Chain code
  * (hex):       b'43088cf562e569922e1c1d0d689144ca2b171cb3cc3b2fedaa198f63be7ec130'
* Serialized
  * (pub hex):   b'0488b21e00000000000000000043088cf562e569922e1c1d0d689144ca2b171cb3cc3b2fedaa198f63be7ec130036830d1cbcecf9e01ce1ddb154ccb754a6a765d06b3b48dced926861e03bd9485'
  * (prv hex):   b'0488ade400000000000000000043088cf562e569922e1c1d0d689144ca2b171cb3cc3b2fedaa198f63be7ec130005c9c29e08d1ee9d3c8295ba2a931a9f0166e4282cc01702549664736a16b3a89'
  * (pub b58):   xpub661MyMwAqRbcFD9E5CavptgKf8JFbkynXnRui6zHDi7TveyV1vnebzqJ1UUDRbcWjBLNy29ABLUxgevE86Pmt3PNMDZFzLyRzQuebs5Kn1G
  * (prv b58):   xprv9s21ZrQH143K2j4kyB3vTkjb76TmCJFwAZWJuiaffNaV3reLUPUQ4CWpABQbzZoo1SvSbuykaZfwj241YvtCs9FVpeKMAFd9eXvQTZwxSNU

顺便说一句,BIP32Key#dump() 的源代码也很好地描述了哪种方法返回哪种格式。

编辑:
mnemonic 库提供了 Mnemonic#to_hd_master_key() 方法,它返回按定义编码的扩展私钥 Base58,例如在bitcon/bipsxprv...。如果这对您来说已经足够了,那么您就不需要 bip32utils
但是,据我所知,mnemonic 不支持从中派生私钥、链码、公钥或扩展公钥。这只是在 bip32utils 类中实现的。
我不清楚哪些库可以使用,哪些不可以。您可能需要自己实现缺少的功能(付出相应的努力):
链码和私钥可以从扩展私钥中确定。为此,您只需要了解格式(参见例如 bitcon/bips)。如果曲线已知(比特币为 secp256k1)(为此需要 ec 算法或 ec 库),则公钥可以从私钥导出,因此是扩展公钥。 bip32utils 可以作为这方面的蓝图。