Made bip32 extended key serialization functions more generic and allow passing params, with default params for master keys. Simplified some of the main.py test code.

This commit is contained in:
Josh K 2019-07-26 02:31:46 -04:00
parent fc0bb21e7f
commit f41b566576
3 changed files with 35 additions and 34 deletions

View File

@ -21,25 +21,21 @@ PRV_VER = bytes.fromhex( '02fac398' if DOGE_MODE else '0488ADE4' )
# 0488B21E - bitcoin pub
# 02facafd - dogecoin pub
PUB_VER = bytes.fromhex( '02facafd' if DOGE_MODE else '0488B21E' )
# return serialized master private key string from master private (key, chain) bytes pair
def serializeMasterPrvKey( master ):
depth = 0
parFP = intBytes( 0, 4 ) # parent fingerprint
childNum = 0
prvroot = base58.encodeCheck( PRV_VER, intBytes( depth, 1 ) +
parFP + intBytes( childNum, 4 ) + master[1] +
b'\x00' + master[0] )
return prvroot
# return serialized master public key string from master private (key, chain) bytes pair
def serializeMasterPubKey( master ):
depth = 0
parFP = intBytes( 0, 4 ) # parent fingerprint
childNum = 0
pubroot = base58.encodeCheck( PUB_VER, intBytes( depth, 1 ) +
parFP + intBytes( childNum, 4 ) + master[1] +
keys.getPubKey( master[0] ) )
return pubroot
# serialize an extended private key (key, chain)
# parfp is the 4byte parent fingerprint
# default parameters assume master key
def serializeExtPrvKey( key, depth=0, parfp=b'\x00\x00\x00\x00', child=0 ):
return base58.encodeCheck( PRV_VER, intBytes( depth, 1 ) +
parfp + intBytes( child, 4 ) + key[1] + b'\x00' + key[0] )
# serialize an extended public key (key, chain)
# key is compressed public point bytes
# parfp is the 4byte parent fingerprint
# default parameters assume master key
def serializeExtPubKey( key, depth=0, parfp=b'\x00\x00\x00\x00', child=0 ):
return base58.encodeCheck( PUB_VER, intBytes( depth, 1 ) +
parfp + intBytes( child, 4 ) + key[1] + key[0] )
# public parent -> public child.
# pub is (key, chain) where key is the compressed pubkey bytes

13
keys.py
View File

@ -4,7 +4,7 @@
from hashlib import new as newhash
from hashlib import sha256
from random import getrandbits
from os import urandom
import base58
import ecdsa
@ -20,15 +20,12 @@ WIF_VER = b'\x9e' if DOGE_MODE else b'\x80'
# 0x1e - dogecoin
ADDR_VER = b'\x1e' if DOGE_MODE else b'\x00'
# gen random 256bit privkey as bytes
def genRandPrvKey():
# replace with os.urandom for the real deal
rawpk = intBytes( getrandbits( 256 ) )
return rawpk
# gen random 256bit prvkey bytes
def genRandPrvKey(): return urandom( 32 )
# get base58 wif privkey from raw privkey bytes
def getPrvKeyWIF( rawpk ):
return base58.encodeCheck( WIF_VER, rawpk + b'\x01' )
def getPrvKeyWIF( prv ):
return base58.encodeCheck( WIF_VER, prv + b'\x01' )
# get hash160 bytes of pubkey bytes. base58Check this for addr
# also used for bip32 ext key identifier. first 32bits of id is the fingerprint

24
main.py
View File

@ -18,20 +18,28 @@ if __name__ == '__main__':
b39seed = bip39.genSeed( b39phrase )
# test bip32
# master (key, chain) bytes
# master private (key, chain) bytes
b32master = bip32.getMaster( b39seed )
# serialize root master prv and pub key
b32masterxprv = bip32.serializeMasterPrvKey( b32master )
b32masterxpub = bip32.serializeMasterPubKey( b32master )
# serialize master ext prv and pub key
b32masterxprv = bip32.serializeExtPrvKey( b32master )
b32masterxpub = bip32.serializeExtPubKey( (keys.getPubKey( b32master[0] ), b32master[1]) )
print( 'BIP39\n', b39phrase + '\n', b39seed.hex() + '\nBIP32\n' +
f'{b32masterxprv}\n{b32masterxpub}\n{base58.decodeCheck( b32masterxprv ).hex()}\n{base58.decodeCheck( b32masterxpub ).hex()}' )
print( 'BIP39 phrase, seed\n\t', b39phrase + '\n\t', b39seed.hex() +
'\nBIP32 master\n' + f'\t{b32masterxprv}\n\t{b32masterxpub}' )
print()
prvmaster = (b32master[0], b32master[1])
prvroot0 = bip32.ckdPrv( prvmaster, 0 ) # m/0
parfp = keys.getPubKeyHash( keys.getPubKey( prvmaster[0] ) )[:4] # parent fingerprint
prvroot0ext = bip32.serializeExtPrvKey(
prvroot0, 1, parfp, 0 )
pubroot0ext = bip32.serializeExtPubKey(
(keys.getPubKey( prvroot0[0] ), prvroot0[1]), 1, parfp, 0 )
print( f'm/0 derived ext keys:\n\t{prvroot0ext}\n\t{pubroot0ext}' )
for i in range( 20 ):
# pubkeys
# pubkey - prvkey
pk = bip32.ckdPrv( prvroot0, i )[0]
print( 'm/0/{}: {} - {}'.format( i, keys.getPubKey( pk ).hex(), keys.getPrvKeyWIF( pk ) ) )
@ -42,6 +50,6 @@ if __name__ == '__main__':
pubaddr = keys.getPubKeyAddr( pubkey )
print( f'prvkey hex: {prvkey.hex()}' )
print( f'b58 wif pk: {keys.getPrvKeyWIF( prvkey )}' )
print( f'pubkey: {pubkey.hex()}\n\thash: {keys.getPubKeyHash( pubkey ).hex()}\n\taddr: {pubaddr}\n\tdecoded: {base58.decodeCheck( pubaddr ).hex()}' )
print( f'pubkey: {pubkey.hex()}\n\thash: {keys.getPubKeyHash( pubkey ).hex()}\n\taddr: {pubaddr}' )
"""