- Notifications
You must be signed in to change notification settings - Fork1
Utilities for generating Bitcoin Hierarchical Deterministic Wallet addresses using BIP0032
License
kcorlidy/bip32utils
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
I add more types of key and fixed two issues 1.check_decode
will ignore leading1
2.fromExtendedKey
parameter, xkey is not necessarily 78 bytes long
defcheck_decode(enc,need_prefix=False):"Decode bytes from Bitcoin base58 string and test checksum"dec=decode(enc)raw,chk=dec[:-4],dec[-4:]ifchk!=sha256(sha256(raw).digest()).digest()[:4]:raiseValueError("base58 decoding checksum error")elifnotneed_prefix:# strictly speaking we should return raw, but to reduce duplicate code i abandoned the first byte# Because the most used of `check_decode` is to decode a address.# And the first bytes of raw is version that we dont need almost.returnraw[1:]# But sometime you will decode something else, i.e. *extendedkey*, etc.# So set `need_prefix = True`returnraw
The bip32utils library is a pure Python implementation of Bitcoinhierarchical deterministic wallet ("HD Wallet") ECDSA key generationas specified in BIP0032 (Bitcoin Improvement Proposal #0032).
Deterministic ECDSA key generation allows creating a sequence ofBitcoin private and public ECDSA keys from an initial seed and ahierarchical set of indices. A number of benefits follow:
An entire wallet can be backed up once by storing the wallet seed ormaster extended private key, and all future addresses in the walletcan be restored from it.
The creation of public and private ECDSA keys may be separated fromeach other. That is, it is possible to create only the public ECDSAkey half (and receiving address) of an ECDSA key pair, without theability to create the private half. Thus, one can create receivingaddresses on a public facing system that if compromised would notgive the attacker the ability to spend bitcoin received at thoseaddresses. A separate, offline machine can generate thecorresponding private ECDSA keys and sign transactions.
Public and private ECDSA keys may be created in a hierarchy, andcontrol over or visibility of portions of the hierarchy may bedelegated to third parties. This has uses for auditing, forseparating ECDSA key sequences into different logical groups oraccounts, and for giving 3rd parties the ability to create spendingtransactions without first getting a receiving address in advance.
BIP0032 is in draft stage, is subject to change, and is documented at:
https://github.com/sipa/bips/blob/bip32update/bip-0032.mediawiki
This library installs the bip32gen script into $PREFIX/bin, whichwraps a command-line interface around the BIP32Key class functionalitydescribed in a later section:
$ bip32gen -husage: bip32gen [-h] [-x] [-X] -i {entropy,xprv,xpub} [-n AMOUNT] [-f FROM_FILE] [-F TO_FILE] -o OUTPUT_TYPE [-v] [-d] chain [chain ...]Create hierarchical deterministic wallet addressespositional arguments: chain list of hierarchical key specifiersoptional arguments: -h, --help show this help message and exit -x, --input-hex input supplied as hex-encoded ascii -X, --output-hex output generated (where applicable) as hex-encoded ascii -i {entropy,xprv,xpub}, --input-type {entropy,xprv,xpub} source material to generate key -n AMOUNT, --amount AMOUNT amount of entropy to to read (bits), None for all of input -f FROM_FILE, --from-file FROM_FILE filespec of input data, '-' for stdin -F TO_FILE, --to-file TO_FILE filespec of output data, '-' for stdout -o OUTPUT_TYPE, --output-type OUTPUT_TYPE output types, comma separated, from addr|privkey|wif|pubkey|xprv|xpub|chain -v, --verbose verbose output, not for machine parsing -d, --debug enable debugging output
The user specifies the type of input data (currently from entropy, aserialized extended private key, or serialized extended public key),the filespec to get that input data from (or stdin), the set of outputfields to generate, whether to hex encode those outputs whenapplicable, and a list of key specifier(s). A key specifier willeither start with 'm' or 'M' when using entropy as an input source;otherwise, when importing from a serialized extended key, the keyspecifier(s) start with the first hierarchical child index to create.
For example, to generate a new master wallet key from entropy andoutput the serialized extended private key for that to stdout:
$ bip32gen -i entropy -f /dev/random -n 128 -o xprv -F - mxprv9s21ZrQH143K3eqKCaAW9CvAiKR8SHdikQnR8dVs8eBxC9fYtW69k1gLRTG5o2Rn3gtz651yFGzxRFjtfjLQHmh4kT7YF3vZcZgGdfX7ZVS
To generate the BIP0032 test vector #1, using entropysupplied as a hex-encoded string on stdin, and output the privateECDSA key, wallet import format for that private ECDSA key, publicECDSA key, address, and serialized extended private and public keys,hex encoding where applicable, and writing to stdout:
$ echo 000102030405060708090A0B0C0D0E0F | \ bip32gen -v \ -i entropy -f - -x \ -o privkey,wif,pubkey,addr,xprv,xpub -F - -X \ m \ m/0h \ m/0h/1 \ m/0h/1/2h \ m/0h/1/2h/2 \ m/0h/1/2h/2/1000000000
(output not listed)
BIP0032 outlines a hierarchy where individual "accounts" and key series have the following form:
m/ih/0/k - Receiving address series for account 'i', with 'k' as indexm/ih/1/k - Change address series for spends from account 'i', with 'k' as index
So, to give someone the ability to create receving addresses foraccount 0, (but not the ability to spend from those addresses), onewould export anextended public key for m/0h/0 (we'll use again theentropy from BIP0032 test vector #1 for purpose of explanation, but ofcourse this would be unique for each situation):
$ echo 000102030405060708090A0B0C0D0E0F | \ bip32gen \ -i entropy -f - -x \ -o xpub -F - \ m/0h/0xpub6ASuArnXKPbfEVRpCesNx4P939HDXENHkksgxsVG1yNp9958A33qYoPiTN9QrJmWFa2jNLdK84bWmyqTSPGtApP8P7nHUYwxHPhqmzUyeFG
Then, to derive public child keys, that person would run thekey generator using that extended public key as input:
$ echo xpub6ASuArnXKPbfEVRpCesNx4P939HDXENHkksgxsVG1yNp9958A33qYoPiTN9QrJmWFa2jNLdK84bWmyqTSPGtApP8P7nHUYwxHPhqmzUyeFG | \ bip32gen \ -i xpub -f - \ -o addr -F - \ 0 1 2 3 4 5 6 7 8 91BvgsfsZQVtkLS69NvGF8rw6NZW2ShJQHr1B1TKfsCkW5LQ6R1kSXUx7hLt49m1kwz751D2LvY1T3yT4xWgoXkXhAbh1fbY39owifJ1L71JnrWfB45Z1g2et1zeDAkzrpY8eyJMH1ACa2mfirthEwmnHVHcBEAVfTHJkajpjod1CR1rZqA8cwbohoj9bNmcrYxx31Zx2jw4c1PkyqPChrqwM1dee8KTMpsWWBuXgmGVNoi1L3HVcGagSUEb2d24SfHV7Kyu6kUNpDL5117JbSP83rPWmbdcdtiiTNqBE8MgGN8kmUk1MWb4Pv4ZCUmbnFgA5D3MtYyhMh4q8KCrd
An offline machine could generate the corresponding private keys tospend from those addresses by using anextended private key for theaccount:
$ echo 000102030405060708090A0B0C0D0E0F | \ bip32gen \ -i entropy -f - -x \ -o xprv -F - \ m/0h/0xprv9wTYmMFdV23N21MM6dLNavSQV7Sj7meSPXx6AV5eTdqqGLjycVjb115Ec5LgRAXscPZgy5G4jQ9csyyZLN3PZLxoM1h3BoPuEJzsgeypdKj
Then to generate the corresponding private keys (here shown in wallet import format):
$ echo xprv9wTYmMFdV23N21MM6dLNavSQV7Sj7meSPXx6AV5eTdqqGLjycVjb115Ec5LgRAXscPZgy5G4jQ9csyyZLN3PZLxoM1h3BoPuEJzsgeypdKj | \ bip32gen \ -i xprv -f - \ -o wif -F - \ 0 1 2 3 4 5 6 7 8 9L3dzheSvHWc2scJdiikdZmYdFzPcvZMAnT5g62ikVWZdBewoWpL1L22jhG8WTNmuRtqFvzvpnhe32F8FefJFfsLJpSr1CYsRrZCyTwKZKwhVMKLLSMt7DemnUxhSftkdqPjWYmPKt31nmV3BB7TdVaMFzqgPKySK2geQrXWYR7f2p9C9Exr4CLngFQnnzQegSaKAfxNupqecSwdUKxSKj3b3EdHSyN3C5sSwRL7TMmxpEVkJ7Cw4fQTMUYXsCZRbmBAPL5kxG5qokHeTJSwco5JzCEdAy5TN2M2Tj2QvxGpvVuSVP5bJRAUTL3oTQGyHQvE3GkRQJkgPs9vY8NRTxdwacHu9Xu9QBPTpgHCSGumeKxABnXp7SiuWi218c14KkjEMV7SjcfXnvsWaveNVxWZU1Rwi8zNQL1Zku8j3mCiiHxZdo6NDLHv6jcA1JyNufUSHBMiznML38vNr9AghL46bxscw878ytxNHro7ghNXuybUv8aNJAY1UudH1HUxD2pecBhR8
The bip32utils python library currently has a single class, BIP32Key,which encapsulates a single node in a BIP0032 wallet hierarchy. Aterminology distinction is made between an ECDSA private and publickey pair and a full BIP32Key, which internally holds an ECDSA key pairand other data.
A BIP32Key may act like a standard Bitcoin keypair, providing themeans to sign transactions with its internal ECDSA private key or togenerate a receiving address with its internal ECDSA public key. Inaddition, a BIP32Key can act as the parent node for a set of indexedchildren and thus form a tree of BIP32Key sequences.
A BIP32Key may also be deemed a private or public BIP32Key, dependingupon whether the secret half of the internal ECDSA key pair ispresent. Private BIP32Keys are able to generate either public orprivate child BIP32Keys, while public BIP32Keys can only generatepublic children.
In other words, a private BIP32Key internally stores an ECDSA privatekey, an ECDSA public key, and some additional pseudorandom bits namedthechain code. Public BIP32Keys are only different in that thesecret half of the ECDSA key pair does not exist; only the public halfdoes.
A BIP32Key may come into existence in one of four ways:
Using the BIP32Key.fromEntropy(entropy, public=False) method, onemay provide a string of at least 32 bytes (128 bits) to construct anew master BIP32Key for an entire tree. From this initial >= 128bits of entropy a new ECDSA private key, ECDSA public key, andpseudorandom chain code are derived that preserves the 128 bitsecurity parameter as described in BIP0032. This is termed a privateBIP32Key, and may be used to derive child BIP32Keys that are eitherprivate or public.
If the public parameter is set to True, then the internal ECDSAprivate key is discarded, the resulting BIP32Key is known as apublic BIP32Key, and may only be used to generate further publicBIP32Keys.
Using the BIP32Key.fromExtendedKey(xkey, public=False) staticmethod, one may provide a 78-byte serialized string that isformatted as an Extended Private Key, as documented in BIP0032. Fromthis, the ECDSA private key, ECDSA public key, and chain code areextracted.
If the public parameter is set to True, then the internal ECDSAprivate key is discarded, converting the resulting BIP32Key into apublic BIP32Key, and may only be used to generate further publicBIP32Keys.
Using the BIP32Key.fromExtendedKey(xkey) static method, one mayprovide a 78-byte serialized string that is formatted as an ExtendedPublic Key, as documented in BIP0032. From this, the ECDSA publickey and chain code are extracted, resulting in a public BIP32Keythat may only be used to generate further public BIP32Keys.
Finally, using an instance of a BIP32Key resulting from any of thethree methods above, one may call the member function ChildKey(i) tocreate a child BIP32Key one level lower in the hierarchy, at integerindex 'i'. If the starting BIP32Key is a private one, then theresulting child BIP32Key will also be a private one, using theCKDpriv derivation formula in BIP0032.
Likewise, if the starting BIP32Key is a public one (i.e., does notcontain an internal ECDSA private key half), then the child BIP32Keywill also be a public one, derived using the CKDpub algorithm inBIP0032.
At any time, a private BIP32Key may be turned into a public one bycalling the instance member function SetPublic(), which discards theinternal private ECDSA key half and sets an internal flag.
When creating a child BIP32Key from an existing private BIP32Key, onemay also select from an alternate set of child keys, calledhardenedkeys, by adding the constant BIP32_HARDEN to the integer index. Ahardened child BIP32Key avoids a known issue with non-hardened childkeys where a compromise of one child key may result in a compromise ofall child keys in the same sequence.