Skip to content

Instantly share code, notes, and snippets.

@ckhung
Last active January 26, 2022 10:39
Show Gist options
  • Save ckhung/dadda37930068227e4b11825869c30d6 to your computer and use it in GitHub Desktop.
Save ckhung/dadda37930068227e4b11825869c30d6 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
# https://medium.com/mycrypto/the-journey-from-mnemonic-phrase-to-address-6c5e86e11e14
# pip3 install bip_utils
# python3 bip_demo.py
# For the 1st example, private key and address of path0
# have been verified using exodus wallet.
# For the 2nd example, the computed master key does not match the article...?
# If you have a private key stored in a file named priv_key_file.txt
# this program will also create a derived pair of keys from it
# as a 3rd example.
# DO NOT use the addresses generated from this sample comination
# of phrases to store your coins!
# import argparse
from bip_utils import (
Bip39Mnemonic, Bip39MnemonicDecoder, Bip39MnemonicEncoder,
Bip39Languages, Bip39SeedGenerator, Bip32Secp256k1, EthAddr
)
def print_master(master):
print(f'master: {master.PrivateKey().Raw().ToHex()}')
priv_key = master.PrivateKey().KeyObject()
print(f'private: {priv_key.Raw().ToHex()}')
print(f'public: {master.PrivateKey().PublicKey().ToExtended()}')
print(f'public: {master.PublicKey().ToExtended()}') # same as above
master2 = Bip32Secp256k1.FromPrivateKey(priv_key)
print(f'master2: {master2.PrivateKey().Raw().ToHex()}') # same as original master key
print('')
def path_demo(parent, path):
print(f'path: {path}')
pathobj = parent.DerivePath(path)
print(type(pathobj))
print(f'private: {pathobj.PrivateKey().Raw().ToHex()}')
eth_pubkey = pathobj.PrivateKey().PublicKey().KeyObject()
print(f'public: {eth_pubkey.RawCompressed().ToHex()}')
eth_pubkey = pathobj.PublicKey().KeyObject()
print(f'public: {eth_pubkey.RawCompressed().ToHex()}') # same as above
eth_addr = EthAddr.EncodeKey(eth_pubkey)
print(f'addr: {eth_addr}')
msg = b'pay 0.01 eth to some addr'
# print(type(pathobj.PrivateKey()))
sig = pathobj.PrivateKey().KeyObject().UnderlyingObject().sign(msg)
# print(type(sig))
print(f'sig: {sig.hex()}')
verify = eth_pubkey.UnderlyingObject().verify(sig, msg)
print(f'verify: {verify}')
fakesig = bytearray(sig)
fakesig[-1] = (fakesig[-1]+1)%256
fakesig = bytes(fakesig)
print(f'fakesig: {fakesig.hex()}')
verify = eth_pubkey.UnderlyingObject().verify(fakesig, msg)
print(f'fakevfy: {verify}')
print()
# parser = argparse.ArgumentParser(
# description='generate information from 12 phrase mnemonic',
# formatter_class=argparse.ArgumentDefaultsHelpFormatter)
# parser.add_argument('phrases', nargs='*', help='hello world ...')
# args = parser.parse_args()
sep_string = '=' * 10
print(f'\n{sep_string} "Journey" article, Part 1 {sep_string}\n')
phrases = 'wild quiz always market robust board \
acid enough twist divert margin route'
mns_eng = Bip39Mnemonic(phrases.split())
entropy = Bip39MnemonicDecoder(Bip39Languages.ENGLISH).Decode(mns_eng)
print(f'mne(eng): {mns_eng}')
print(f'entropy: {entropy.hex()}')
mns_cht = Bip39MnemonicEncoder(Bip39Languages.CHINESE_TRADITIONAL).Encode(entropy)
entropy = Bip39MnemonicDecoder(Bip39Languages.CHINESE_TRADITIONAL).Decode(mns_cht)
print(f'mne(cht): {mns_cht}')
print(f'entropy: {entropy.hex()}')
seed = Bip39SeedGenerator(mns_eng).Generate()
print(f'seed: {seed.hex()} [<= we will use this]')
seed_cht = Bip39SeedGenerator(mns_cht, Bip39Languages.CHINESE_TRADITIONAL).Generate()
print(f'seed_cht: {seed_cht.hex()} [discarded]')
print(f'[ seed gen. is lang-dependent! https://bitcoin.stackexchange.com/q/88115 ]')
master = Bip32Secp256k1.FromSeed(seed)
print_master(master)
path0 = "m/44'/60'/0'/0/0"
path_demo(master, path0)
pathobj0 = master.DerivePath(path0)
path_demo(pathobj0, '3')
path_demo(master, path0 + '/3')
print(f'\n{sep_string} "Journey" article, Part 2 {sep_string}\n')
seed = '77cdf1d92225adc0e67b1b4f5a31820251d518b3af074df25a07b751947fd07ebd29a4d0e57b84ea9de03a9123e2a6ea1e3ed739d4c562efec21f1bb0a54a879'
print(f'seed: {seed}')
master = Bip32Secp256k1.FromSeed(bytes.fromhex(seed))
print_master(master)
path_demo(master, path0)
from os import access, R_OK
from os.path import isfile
import binascii
priv_key_file = 'priv_key_file.txt'
if isfile(priv_key_file) and access(priv_key_file, R_OK):
print(f'\n{sep_string} priv key from file: {priv_key_file} {sep_string}\n')
with open(priv_key_file) as F:
priv_key = F.read().rstrip()
priv_key = binascii.unhexlify(priv_key)
master = Bip32Secp256k1.FromPrivateKey(priv_key)
print_master(master)
path0 = "17"
path_demo(master, path0)
# hierarchical deterministic wallet
# dot -Tsvg hdwallet.dot > hdwallet.svg
# The generated hdwallet.svg file was then manually edited using inkscape
digraph "hdwallet" {
rankdir = LR;
overlap = scale;
node [shape=rectangle];
mne [ label="mnemonics (en_US)\nwild ... route" ];
entropy [ label="entropy\nfb15...1fde" ];
mne_cht [ label="mnemonics (zh_TW)\n辨 縫 ... 亦 齡" ];
seed [ label="seed\nfd0e...3dbf" ];
master [ label="master\n329a...8208" ];
entropy -> mne:ne [ label="Bip39MnemonicEncoder()" ];
mne -> entropy:sw [ label="Bip39MnemonicDecoder()" ];
entropy -> mne_cht [ label="Bip39MnemonicEncoder()"; style="dashed" ];
mne_cht:sw -> entropy:se [ label="Bip39MnemonicDecoder()"; style="dashed" ];
mne:se -> seed [ label="Bip39SeedGenerator()"; ];
seed:se -> master:sw [ label="Bip32Secp256k1.FromSeed()" ];
master -> { rank = same; public; private }
private -> { public; master }
public -> address;
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@ckhung
Copy link
Author

ckhung commented Jan 1, 2022

wild-quiz-*-route

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment