Last active
January 26, 2022 10:39
-
-
Save ckhung/dadda37930068227e4b11825869c30d6 to your computer and use it in GitHub Desktop.
Demo of bip_utils to accompany https://medium.com/mycrypto/the-journey-from-mnemonic-phrase-to-address-6c5e86e11e14
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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; | |
} | |
Author
ckhung
commented
Jan 1, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment