I want to keep off-site paper-backups of my seed, but that increases the risk of a physical attack. Can I somehow split my Mnemonic Code into three parts that I only need two of to recover my trezor?
I see Shamir Secret Sharing recommended; yet One Time Pad or XOR is an elegant way to split a BIP39 seed. It's a method simple to describe (apt for a will), easy to verify (trust only yourself) and like SSS is information-theoretic secure . It can be computed entirely with paper and pencil eliminating risks from malware and best of all the resulting shares are themselves mnemonics thus convenient to record (cryptosteel). The method does not scale efficiently for "n of m" when m is large, but works well for "n of n", "2 of 3" and "3 of 5".
Consider an example of a three word mnemonic from the 2048 word BIP-0039 dictionary:
S = "night love grit"
We will split the seed S into two parts, A and B, such that A + B = S (where + is element wise addition mod 2048). First generate a random key A of the same length, say A = "steel siren layer". To find the second key B, go word by word subtracting the dictionary indexes mod 2048 of A from S:
1st: (night - steel) mod 2048 = (1197 - 1706) mod 2048 = 1539 = scare
2nd: (love - siren) mod 2048 = (1060 - 1612) mod 2048 = 1496 = road
3rd: (grit - layer) mod 2048 = (822 - 1011) mod 2048 = 1859 = tribe
Thus B = S - A = "scare road tribe". To retrieve S add the two keys together:
1st: (steel + scare) mod 2048 = (1539 + 1706) mod 2048 = 1197 = night
2nd: (siren + road) mod 2048 = (1496 + 1612) mod 2048 = 1060 = love
3rd: (layer + tribe) mod 2048 = (1859 + 1011) mod 2048 = 822 = grit
Thus as promised, S = A + B. Even with infinite computing power A and B reveal zero information about S. Individually they are nothing but random numbers. "3 of 3" can be achieved by generating two random keys, say A and B. Then the third key C is found as:
C = S - A - B; giving S = A + B + C. This can be extended to "n of n".
For "2 of 3" repeat the method three times. Each time use a different random key A; say A1, A2 and A3. This generates three keys B1, B2 and B3. So now we have:
A1 + B1 = S
A2 + B2 = S
A3 + B3 = S
Divide the keys like this:
Switzerland: A1, A2
Canada: A3, B1
New Zealand: B2, B3
Vires in Numeris!
One can use Shamir's Secret Sharing Scheme, but the input ASCII string must be under 128 ASCII characters in length. Fortunately, the 2048 English BIP 39 words are guaranteed to be unique from their 1st four characters, sometimes even fewer characters.
Let's assume the 24 recovery words are "bunker wreck real edge inflict aerobic buddy mercy divorce wolf bright immune fat foot poet section sustain reveal unique reflect have latin problem chapter", which is longer than 128 characters.
The shortened string becomes "bunk wrec real edge infl aero budd merc divo wolf brig immu fat foot poet sect sust reve uniq refl have lati prob chap". The full word length can be reconstituted by examining complete list of 2048 English BIP 39 words.
% echo "bunk wrec real edge infl aero budd merc divo wolf brig immu fat foot poet sect sust reve uniq refl have lati prob chap" | ./ssss-split -t 2 -n 3 -w MyWill WARNING: couldn't get memory lock (ENOSYS, kernel doesn't allow page locking). Generating shares using a (2,3) scheme with dynamic security level. Enter the secret, at most 128 ASCII characters: Using a 944 bit security level. **MyWill-1-e77f7d1fbeca7f35fc9735f698df76e3aa6187c5b8b1110ab1b249b69435fd23f3e35724736f0a76aa3157d8c483f9a633ba254dc518fda26ec1ee0907a7dc8dba1a9733ab14038b0f2e42ce8ad457192befa42c8afa7d55d739f07e7f252463610b1030283002941187b0fc2e423730af25d54807da** **MyWill-2-bbf6fc411a6cce683b26bd888aed207ba3ef8aa8235a89010031f67f565bfbebd6e410e2cd16145bb28475d2b71eba8fccecb5bcf881e3eb26ba8d5f65ee61a6981052f8eab864e8a7b582e969cc34ec917157303005d674584ad57e0097bb9408a83948d4960d29316a548bce8c4ecee23ad7474436** **MyWill-3-70718374860ea15c8649c5a284fcedf3a4958e7355fc010790b09cc7e87e0653ca192da0a73ee1bf45176bd49995846899dec5ec13f6e9d3e16c5392bbd6f54079e9ee41d5dc46363fc33d0bc8c415bff8fb063ba650b094dd64367e2a0631392fc9219f7f0bf7bdd13108a691366664d9302942736f** % ./ssss-combine -t 2 WARNING: couldn't get memory lock (ENOSYS, kernel doesn't allow page locking). Enter 2 shares separated by newlines: Share [1/2]: MyWill-1-e77f7d1fbeca7f35fc9735f698df76e3aa6187c5b8b1110ab1b249b69435fd23f3e35724736f0a76aa3157d8c483f9a633ba254dc518fda26ec1ee0907a7dc8dba1a9733ab14038b0f2e42ce8ad457192befa42c8afa7d55d739f07e7f252463610b1030283002941187b0fc2e423730af25d54807da Share [2/2]: MyWill-3-70718374860ea15c8649c5a284fcedf3a4958e7355fc010790b09cc7e87e0653ca192da0a73ee1bf45176bd49995846899dec5ec13f6e9d3e16c5392bbd6f54079e9ee41d5dc46363fc33d0bc8c415bff8fb063ba650b094dd64367e2a0631392fc9219f7f0bf7bdd13108a691366664d9302942736f **Resulting secret: bunk wrec real edge infl aero budd merc divo wolf brig immu fat foot poet sect sust reve uniq refl have lati prob chap**
The same Shamir's Secret Sharing Scheme can also be applied to a complementary BIP 39 passphrase.
My personal preferences:
Stick to known-good algorithms like Shamir's Secret Sharing Scheme whose security properties are well-understood, rather than trying to invent something new.
Reuse existing tools and formats/encodings, so you aren't dependent on something obscure or homemade that might not be maintained 10 years from now.
Try to encode the seed using mnemonics, with as few words as possible, to reduce the potential for human error. Typing in long hex strings isn't very user-friendly, and passing them around in electronic form can create the potential for inadvertent leaks.
With that in mind, here is what I'd propose:
0) Install the appropriate command-line tools:
$ sudo apt install cpanminus build-essential ssss $ sudo cpanm App::BIP39Utils
1) Convert your 24-word recovery seed back into a 256-bit hex number:
$ bip39-mnemonic-to-entropy "spider tongue exclude enable wise vacuum cereal cereal rescue stone wash remain ahead goose scene relief buzz believe arm rely result volume appear cave" \ | tee seed.txt d1bc8d3ba4afc7e109612cb73acbdddac052c93025aa1f82942edabb7deb82a1
2) Use SSSS to split the raw hex seed. Using the raw seed as the input is important: it means the shares will be 256 bits long and can themselves be encoded using BIP39:
$ ssss-split -q -t 2 -n 3 -x < seed.txt | tee shares.txt 1-0b16c10b9597bc0d6a0223b25c5536b942bfe17ed5887a341e9dfbc1c878c36f 2-d312bb875b9f9273ec8a8cb5a1385274bac3cc5b1d5bf6b17f8b0f1c9953abbe 3-64ee92031e678859910d1648f5e371cfed17d747a51572cda086a357a9b57010
3) Encode each of the shares into a 24-word phrase using BIP39:
$ cat shares.txt | \ ( IFS=-; while read i s; do echo "$i: `entropy-to-bip39-mnemonic $s`"; done ) 1: arch render drill clinic knock allow pool dutch rather tired ethics income cloud vague win rain kick path polar wasp broken detect asset want 2: spread noise tide rescue weird delay rate face remember antenna behind truly promote tower hockey problem wall message tissue bullet sister prefer puzzle stumble 3: gossip innocent liar devote joy coast during people employ pyramid symbol panther sphere two burden pencil index home canvas effort kind survey scare beef
4) Write down each share on a separate sheet of paper. Store (1) in your sock drawer, (2) with your estate lawyer, and (3) in your safe deposit box. Or whatever. Remember to write down both the share number and the threshold on each sheet.
5) To reconstruct the recovery seed phrase, convert any two shares from BIP39 to hex:
$ echo 1-`bip39-mnemonic-to-entropy "arch render drill clinic knock allow pool dutch rather tired ethics income cloud vague win rain kick path polar wasp broken detect asset want"` \ > combine.txt $ echo 3-`bip39-mnemonic-to-entropy "gossip innocent liar devote joy coast during people employ pyramid symbol panther sphere two burden pencil index home canvas effort kind survey scare beef"` \ >> combine.txt $ cat combine.txt 1-0b16c10b9597bc0d6a0223b25c5536b942bfe17ed5887a341e9dfbc1c878c36f 3-64ee92031e678859910d1648f5e371cfed17d747a51572cda086a357a9b57010
$ echo 2-`bip39-mnemonic-to-entropy "spread noise tide rescue weird delay rate face remember antenna behind truly promote tower hockey problem wall message tissue bullet sister prefer puzzle stumble"` \ > combine.txt $ echo 3-`bip39-mnemonic-to-entropy "gossip innocent liar devote joy coast during people employ pyramid symbol panther sphere two burden pencil index home canvas effort kind survey scare beef"` \ >> combine.txt
Or 1 and 2.
6) Then combine them using SSSS, to return the original hex seed from step 1:
$ ssss-combine -q -t 2 -x < combine.txt d1bc8d3ba4afc7e109612cb73acbdddac052c93025aa1f82942edabb7deb82a1 $ entropy-to-bip39-mnemonic d1bc8d3ba4afc7e109612cb73acbdddac052c93025aa1f82942edabb7deb82a1 spider tongue exclude enable wise vacuum cereal cereal rescue stone wash remain ahead goose scene relief buzz believe arm rely result volume appear cave
Some security considerations:
Only handle seeds on an air-gapped computer booted from trusted media (e.g. a live Linux CD). Unplug the network and any HDDs prior to entering any secrets on the system, and power off the system before plugging anything back in. You don't want any of this data to be inadvertently stored or transmitted to the network.
Never use a printer to record seed data. Traces of printed output may be recoverable from e.g. paper rollers. It might persist in the printer's memory.
Some live CD images might automatically use any swap partitions they find on the system. Beware.
If you are writing down BIP39 phrases, consider what is underneath the paper. For instance, if you are using 3 consecutive sheets from a notepad, it may be possible to reconstruct information by looking at the impressions left in the paper.
If you're paranoid, cover up any phone/laptop cameras whenever you handle recovery seeds.
The bip39-standalone web tool may be usable in lieu of App::BIP39Utils.
BIP 39 has no such standard for doing so, and AFAIK, there is no standard for splitting a seed like that. However you could create something that uses Shamir's Secret Sharing to split the seed (which the mnemonic encodes) into parts and then encode those parts as something memorable like the mnemonic. But AFAIK, there is no software that does this for you.
Create a 2 of 3 multisig wallet using electrum or copay. You'll get 3 seeds any 2 of which need to be used to spend your coins. Alternatively create a 2 of 4 multisig wallet. You can create any combination involving up to 15 co-signers. Here's a guide for electrum in case you are interested.
I created a Nodejs library and command line tool that can do exactly this. Currently it only works with a raw private key of almost any length, but I would like to enhance it to work directly with BIP39 seeds as well. It uses one time padding on the keys as well, making any of the 3 split keys as strong as the original one. It also generates bar codes for each of the three split keys.
I'm working on a little webapp (that runs fully client side of course) that can be used to generate the split keys, as well as scan in the split keys to restore the original key.