1

I basically followed the instructions here How to generate mycelium addresses from the 12 words in python

So my code is similar:

from bip32utils import BIP32Key
from bip32utils import BIP32_HARDEN
from bip32utils import Base58
import os, bip39

strength_bits = 128
entropy = os.urandom(strength_bits // 8)
wallet_generator = bip39.Mnemonic('english')
mnemonic = wallet_generator.to_mnemonic(entropy)
assert wallet_generator.to_entropy(mnemonic) == entropy  # see, bijective!

# Or specify the mnemonic directly if you prefer:
mnemonic = 'aware report movie exile buyer drum poverty supreme gym oppose float elegant'
passphrase = 'test'

seed = bip39.Mnemonic.to_seed(mnemonic, passphrase=passphrase)
key = BIP32Key.fromEntropy(seed)
account_number = 0
i = 0
print "Address: " + key.ChildKey(44 + BIP32_HARDEN) \
         .ChildKey(0 + BIP32_HARDEN) \
         .ChildKey(account_number + BIP32_HARDEN) \
         .ChildKey(0) \
         .ChildKey(i) \
         .Address()

And I verified it using https://iancoleman.io/bip39/#english that the generated address is indeed the first address that this webpage generated as well. However, I also want to get the public and private key pairs using this same library. I originally tried:

print "Public Key: " + Base58.check_encode(key.ChildKey(44 + BIP32_HARDEN) \
         .ChildKey(0 + BIP32_HARDEN) \
         .ChildKey(account_number + BIP32_HARDEN) \
         .ChildKey(0) \
         .ChildKey(i) \
         .PublicKey())

print "Private Key: " + Base58.check_encode(key.ChildKey(44 + BIP32_HARDEN) \
         .ChildKey(0 + BIP32_HARDEN) \
         .ChildKey(account_number + BIP32_HARDEN) \
         .ChildKey(0) \
         .ChildKey(i) \
         .PrivateKey())

However, the output of these two calls are not the same as the ones provided by the website above for the same address.

So my question is: what's the proper way for me to generate the public and private key pairs?

Edit: To clarify, for the exact mnemonic and passphrase above, the website I'm using for reference tells me the first address and keypair should be: enter image description here

While the output of the above python code is:

Address: 1K6WQtD7bLQ5nQ14GyBV33mBWSbkiRKhQs
Public Key: 62Yi9HBYYagf8CY1Ve2fquHKjBqAA7GFjGUUtkUHbkP5PHzv3W
Private Key: EGHMsAp7nY7Jo9F589zCU227KBLTDhiwRq5vYVvRVZxJNPJn4

So the address matches, but not the keypair.

  • take a look at this: bitcointalk.org/index.php?topic=1060451.0 – Zombie Jun 27 '18 at 11:07
  • Are you sure it's not matching? I see you are using PublicKey() vsAddress(), did you want the public key or the address? – m1xolyd1an Jun 28 '18 at 5:14
  • I want the public key and the private key. The address is already correct. I've edited the question to add the sample output of both the reference webpage and the python script for reference – Stormy Dan Jun 28 '18 at 6:19
1

Please try the following demo, and the result is same with https://iancoleman.io/bip39/.

$ python3.6 test.py
{'addr': '1A9vZ4oPLb29szfRWVFe1VoEe7a2qEMjvJ',
 'coin': 'BTC',
 'mnemonic_words': 'aware report movie exile buyer drum poverty supreme gym oppose float elegant',
 'privatekey': 'L3g3hhYabnBFbGqd7qReebwCrRkGhAzaX4cBpYSv5S667sWJAn5A',
 'publickey': '029dc2912196f2ad7a830747c2490287e4ff3ea52c417598681a955dcdf473b6c0'}

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pprint
import binascii
import mnemonic
import bip32utils

def bip39(mnemonic_words):
    mobj = mnemonic.Mnemonic("english")
    seed = mobj.to_seed(mnemonic_words)

    bip32_root_key_obj = bip32utils.BIP32Key.fromEntropy(seed)
    bip32_child_key_obj = bip32_root_key_obj.ChildKey(
        44 + bip32utils.BIP32_HARDEN
    ).ChildKey(
        0 + bip32utils.BIP32_HARDEN
    ).ChildKey(
        0 + bip32utils.BIP32_HARDEN
    ).ChildKey(0).ChildKey(0)

    # return {
    #     'mnemonic_words': mnemonic_words,
    #     'bip32_root_key': bip32_root_key_obj.ExtendedKey(),
    #     'bip32_extended_private_key': bip32_child_key_obj.ExtendedKey(),
    #     'bip32_derivation_path': "m/44'/0'/0'/0",
    #     'bip32_derivation_addr': bip32_child_key_obj.Address(),
    #     'coin': 'BTC'
    # }

    return {
        'mnemonic_words': mnemonic_words,
        # 'bip32_root_key': bip32_root_key_obj.ExtendedKey(),
        # 'bip32_extended_private_key': bip32_child_key_obj.ExtendedKey(),
        # 'path': "m/44'/0'/0'/0",
        'addr': bip32_child_key_obj.Address(),
        'publickey': binascii.hexlify(bip32_child_key_obj.PublicKey()).decode(),
        'privatekey': bip32_child_key_obj.WalletImportFormat(),
        'coin': 'BTC'
    }


if __name__ == '__main__':
    mnemonic_words = "aware report movie exile buyer drum poverty supreme gym oppose float elegant"
    pprint.pprint(bip39(mnemonic_words))
0

I found the problem I think.

You should not do the Base58.check_encode

To print the PublicKey, use the .hex() method.

Also, https://iancoleman.io/bip39/#english print Private key in the WIF form so you should do .WalletImportFormat() instead of .PrivateKey() if you want do have the same output as iancoleman.io . This time, no need to use .hex() (again no need to encode in base58)

0

The public key should be in hex as @MohamedLEGH pointed out above. Regarding the private key you have to append the network code to it first. See step 2 here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.