Tuesday, April 15, 2014

Explaining BIP 0032 using pybitcointools

BIP 0032 is a protocol created to make Hierarchical Deterministic wallets. Most Bitcoin wallets contain a set a private keys that are all randomly generated and have no relationship to each other. Hierarchical Deterministic (HD) wallets contain private keys that are all derived from the same seed. If you can remember your seed, you can regenerate the entire wallet with all the keys. An advantage to this is that you can perform your customary best practices generating new addresses for change for each transaction and if anything happens you can tear down and build the same chain with the same generated addresses as before so you don't lose anything.

BIP 0032 does one step better though. If all you wanted was a chain of private keys that you could reproduce at a whim then why not just transform your seed for your first private key and double SHA-256 hash (the previous key + seed) or some other simple transformation that will achieve the same results (ie. a repeatable chain of private keys)?  The extra level of awesome that BIP 0032 does is that you can produce a public key to generate a public keychain that follows your private keychain.  This public key can be made public (or given to a third party) without compromising your private keys.

There are a couple examples showing why a deterministic public keychain is so important:

1. You can use it on public servers for automated point of sale.  If you want to generate a new address for each order you can use the public chain key to generate these new addresses.  If your server gets compromised, no one can steal your bitcoin because the public chain key can only generate public keys.

2. You can give the public chain key to an auditor.  Lets say you have investors and they want real time audits of your bitcoin sales.  They can give them the public chain key and they will have all the information they need to see transactions without having access to the bitcoin.


So here is how you can use BIP 0032 by utilizing pybitcointools.  Start by asking for the seed input and create from that your master private key.


#Always include pybitcointools
import sys, os
sys.path.append('pybitcointools')
import bitcoin

bip32seed = raw_input('Your secret phrase: ').strip()
masterKey = bitcoin.bip32_master_key(bip32seed)

This "masterKey" is the head of the private keychain.  Now we can start deriving other private keys at the first level of our tree.


level1Priv1 = bitcoin.bip32_ckd(masterKey, 1)
level1Priv2 = bitcoin.bip32_ckd(masterKey, 2)

Here we have derived 2 private chain keys one level down from the masterKey.  Structurally, level1Priv1 and level1Priv2 are no different from masterKey.  Because of this, each private chain key can be used to derive a whole new level of private keys.  So you can code something like this and it is perfectly valid and reproducible:


level1Priv = bitcoin.bip32_ckd(masterKey, 34)
level2Priv = bitcoin.bip32_ckd(level1Priv, 2983)
level3Priv = bitcoin.bip32_ckd(level2Priv, 7)

This would create a private chain key off the masterKey (at the 34th index) and another private chain key off of that (at the 2983rd) index and another off of that (at the 7th index) and from there you can generate a list of private keys off level3Priv at 1, 2, 3, 4, etc.

So now we have the private chain keys but what we would really like is the private key.  That is done like this:


private1 = bitcoin.bip32_extract_key(level1Priv1)

If you want to get the public key that corresponds to this private key there are 2 ways to do that.


level1Pub2 = bitcoin.bip32_privtopub(level1Priv2)
public2 = bitcoin.bip32_extract_key(level1Pub2)

-or-

masterPub = bitcoin.bip32_privtopub(masterKey)
level1Pub2 = bitcoin.bip32_ckd(masterPub, 2)
public2 = bitcoin.bip32_extract_key(level1Pub2)

Each private chain key has its public counterpart.  In the first example we take the public counterpart of the target private chain key and pull out the public key with "bip_extract_key".  In the second example we pull the public chain key from the masterKey which is just a private chain key.  From there we derived public chain key of our target through the public chain.  Note that we were targeting the private key at the 2 index so we make sure and create the public key at the 2 index as well.

These public and private derived keychains are mirrored down as many levels as you would like and across a very large number of indexes with one exception.  You can make a hardened keychain where only private keys may be derived.  This is done by creating the keys at indexes at or above 2^31 or 2147483648.  The public derivation does not work for indexes above that value.

1 comment:

  1. "You can give the public chain key to an auditor. Lets say you have investors and they want real time audits of your bitcoin sales. They can give them the public chain key and they will have all the information they need to see transactions without having access to the bitcoin."

    How is this accomplished in pybitcointools? Great guide!

    ReplyDelete