iancoleman / bip39

A web tool for converting BIP39 mnemonic codes
https://iancoleman.io/bip39/
MIT License
3.49k stars 1.44k forks source link

Allow Serialization of a 64 Byte BIP39 Seed into a BIP32 Root Key #160

Closed jonvaage closed 6 years ago

jonvaage commented 6 years ago

I'd like to request the ability to serialize a 64 byte BIP39 seed in hexadecimal into the corresponding BIP32 root key (xpriv). Currently, the field for the BIP39 seed does not permit user input.

iancoleman commented 6 years ago

Just curious, what's the reason for entering the BIP39 seed hex instead of the mnemonic? Does this mean the 64 bytes has been recorded instead of the mnemonic?

For my own future reference, this is the role of the 64 bytes

To create a binary seed from the mnemonic, we use the PBKDF2 function with a mnemonic sentence (in UTF-8 NFKD) used as the password and the string "mnemonic" + passphrase (again in UTF-8 NFKD) used as the salt. The iteration count is set to 2048 and HMAC-SHA512 is used as the pseudo-random function. The length of the derived key is 512 bits (= 64 bytes).

This seed can be later used to generate deterministic wallets using BIP-0032 or similar methods.

jonvaage commented 6 years ago

I'd like to allow for two forms of recovery:

  1. mnemonic + passphrase (memorized & never written down)
  2. M-of-N fragments of the 64 byte BIP39 seed

The first method is for more convenient, personal access with lower security requirements for the mnemonic itself because of the passphrase requirement.

The second method is a fallback for recovery without the passphrase, in case it's forgotten or I become incapacitated. This allows for more aggressive security measures, including geographically dispersed fragments.

The command line implementation of Shamir's Secret Sharing Scheme (ssss) includes a hex mode which allows for compact fragmentation of this 64 byte digest. Each piece is then small enough to fit in a crypto-steel.

hatgit commented 6 years ago

@jonvaage Wouldn't backing-up only the Rootkey limit your recovery only to certain coins, whereas backing up the initial entropy would allow you to recreate the extended private key (Xpriv) for all accounts? For example, choose Doge coin and the Xpriv changes, but using the initial ent, you can deterministically arrive at that whichever xpriv whether for Doge or any other supported coin by entering the initial entropy into the tool.

If I am correct (with the above, and additional coins are desired to backed-up too unless they are intended to be purposefully excluded, then pardon me), perhaps it would be better to backup the initial entropy instead? For example, the filtered entropy is already in hex format, and 32-64 hex characters depending on if you choose 12 or 24 words to generate using this tool. That initial entropy hex string could then be encrypted and split with Shamir's scheme. Not sure how to include the passphrase in the backup, below is one way perhaps (I thought of it so that if someone knows your mnemonic or its intiial entropy, that would be sufficient to recreate the passphrase).

As far as the passphrase challenge in this case, one idea (not sure if this makes it less secure or changes any attack surface area) is using say the entire initial ent as the passphrase. Note: I believe using the initial ent as the passphrase provides no real added security beyond obscurity as someone could derive your initial entropy from the mnemonic alone and try that as the passphrase. Therefore, if you choose some other source for the passphrase not related this tool's random numbers generated, or resulting mnemonic/data, I'm unaware of any other methods aside from the one you proposed that would be limited to specific coins, that could back up all coin/accounts tied to the same Xpriv.

Here are some examples that can be entered in the tool (that I generated with BIP39 Tool here) and the resulting strings (mnemonic+: passphrase) should fit in the crypto steel plate if you stay with 12 word ones I think)

Init ent in Hex (32 bytes): 460b8282e1967baa17424f856a3e762e

Init ent in binary (256 bits): 01000110000010111000001010000010111000011001011001111011101010100001011101000010010011111000010101101010001111100111011000101110

Resulting 12 word mnemonic: ecology foster pass segment guilt steak fringe enemy lyrics faint outside fruit

BIP 39 seed (128 bits): 5ce6de5236079a22cb267cdb4c3535434603d73ce76303ad6e327b5b82b417035ba76316481fce130770dbd7cbc818c01c639fc1d61b09abe92b5c1a0fb404b4

Extended Public key (bitcoin) xprv9s21ZrQH143K44NF9mfRhJa4eUppXT2WW3Y53qDtw7dkcjVbPtFmq9bAVB8Z9HTbhpLxHmT5vh69wwboLZBVSWg6qyRdVMscCzmfSztP7G6

Extended Public Key (doge coin): dgpv51eADS3spNJh9vevWrPRNgG7zFSBAMsAd7szGREm1YuTVg7WUKYcQhah8HjQDSY5bz2QcZWFU178ckiv7sDUA8vt19Mrdj1XCd4r17UFkw7

w/ inti ent as passphrase: 460b8282e1967baa17424f856a3e762e

BIP 39 Seed:

d30188ab83d452aca2c09dc71c4ca731c0b93fd10a446d9fd4fbaf4779c0daf77fb585b5ac8cc099cd65839966e036a59ff1d09a9e55d3595e4504ef927abea1

Extended Public Key (bitcoin):

xprv9s21ZrQH143K2hd59kWAd7gwxsg7h4HJ7Cq5cSYN5qPhV5928Nhuungqpsg6WJBePnA9nJyZtb8wqx7RhYAJ7svTeLnndWhxWWQFzD5oA1E

Extended Public Key (doge coin):

dgpv51eADS3spNJh8ZukWqEAJVP1JeHUKy7xEHAzq2ZEAGfQN1kwCozkVLgNTzGwaTG8Hwqc772jRu9vWmEYUrCGqWBEoWj1msqsW8hSYNZBFa5

iancoleman commented 6 years ago

I'd like to allow for two forms of recovery

Sure, but that's specific for you, so I think best to fork this tool and adapt it to your needs. This is a general purpose tool and in general the mnemonic is the only source of truth. That's the whole point of mnemonics.

Wouldn't backing-up only the Rootkey limit your recovery only to certain coins

No. This is true for the bip32 root key (base58 encoded) which changes for each coin, but the bip39 seed (hex encoded in the tool) which is the subject of this issue does not. It changes per language but not per coin.

The following convertibility applies:

entropy <-> mnemonic -> bip39 hex seed <-> bip32 xprv -> derived keys

perhaps it would be better to backup the initial entropy instead

No, this is the whole point of mnemonics, to not have to back up binary data.


To address the original issue:

I'd like to request the ability to serialize a 64 byte BIP39 seed in hexadecimal into the corresponding BIP32 root key (xpriv).

Rather than make this a feature of the tool, here's the line that does this:

index.js L465

bitcoinjs.bitcoin.HDNode.fromSeedHex(YOUR_HEX_STRING).toBase58();

Use the console of the dev tools of your browser to make it happen. I don't see any reason to make this field writable to users.