Skip to content

Instantly share code, notes, and snippets.

@axic
Last active April 27, 2016 11:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save axic/d788b0a3fc7ff0608db054ef0fc5dee0 to your computer and use it in GitHub Desktop.
Save axic/d788b0a3fc7ff0608db054ef0fc5dee0 to your computer and use it in GitHub Desktop.
Ethereum HD KDF

There's a long discussion about using BIP32 (the Bitcoin HD wallet KDF) and BIP44 (the KDF path standard) for Ethereum.

It was raised that perhaps a different scheme could be useful.

How Bitcoin HD wallets work?

  1. A mnemonic (i.e. a list of memorable words) is generated (see BIP39)

  2. This mnemonic is converted to a seed using PBKDF2 (see BIP39)

  3. The seed is used to generate root private key using SHA512-HMAC (see BIP32)

  4. From this root key, sub keys are derived (see BIP32), where the node layout is set by BIP44

BIP32

What makes BIP32 useful:

  • in use for multiple years and was subject to more scrutiny
  • multiple implementations in multiple languages exist (with varying level of quality)
  • multiple hardware solutions implement it
  • can support a wallet, where the same nodes are used as keys for Bitcoin and Ethereum (bad idea)

Where BIP32 may be lacking:

  • it doesn't magically make Ethereum work with those BIP32 implementations (including hardware wallets). They are pretty much catered for Bitcoin only.
  • the path structure is very rigid (each path element is practically limited to 31 bits), fitting in long data (such as token addresses) feels a bit clumsy
  • it is battle tested, but that doesn't mean it couldn't be improved (see this recent proposal for improving edge-cases)

Ethereum scheme

Requirements:

  1. be compatible with the Bitcoin scheme as much as possible

  2. use native Ethereum methods where possible

  3. support per-contract (token) layouts

  4. should it support the ability for outsiders to derive public keys?

  5. should have a deterministic way to solve the node skipping issue (where a path would result in an invalid private key)

  6. should it have a way for node discovery? (see BIP44)

Derivation paths

  • <network hash>/general/<n>
  • <network hash>/contract/<contract addr>/<n>
  • <network hash>/token/<contract addr>/<n>

Where <n> is a counter starting from 0.

Simple derivation

It should share the same seed as output by BIP39. This means the same seed can be shared by BIP32 and this scheme.

A given private key can be calculated via: privKey = sha3(rlp([seed, [path array]]))

This doesn't satisfy points 4), 5) and 6) of the requirements.

A possible solution for 5) is to have a nonce to increment as the last parameter of the RLP if an invalid node is derived.

A possible solution for 4) is to move the nonce outside the RLP and use it via the public key derivation used in BIP32.

@axic
Copy link
Author

axic commented Apr 26, 2016

A wild idea for node discovery:

  1. Store the derived paths in a text format (maybe JSON?) and encrypt it with a specific node

  2. Store the encrypted list in IPFS/Swarm

  3. Have a "namereg" to map the IPFS/Swarm address to an address of another specific node

@subtly
Copy link

subtly commented Apr 27, 2016

I would propose this simple scheme until we can spend more time coming up with a richer scheme:

privKey = sha3(seed || rlp([genesis, nonce]))

BIP32/44 is not recommended unless it is already being used. Rationale: 0) keccak has advantages over sha2, 1) bip32 not supported by mainline client, 2) Ethereum doesn't use change addresses, 3) privacy implications, 4) contract-based solutions are a suitable and encouraged alternative. For applications which can't wait for keccak ckdpub derivation and contract solutions, I would propose a path of m/44'/60'/account'/n be used for BIP32 ckdpub keys.

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