Author

Topic: My technique to split seed for cold storage (Read 1293 times)

legendary
Activity: 4466
Merit: 3391
I was looking for a technique to store a wallet seed. Because if somebody find your seed that person can steal the bitcoins. I found a way to split the seed in two parts for cold storage.
...
Finally to obtain "encryption seed B" for each word you need to calculate index(word_seed) - index(word_encryption_a) % 2048.

Your method is similar to this one: XOR Seed Splitting: Theory and Practice

I've looked into that one and Shamir's Secret Sharing, and the major drawback with regards to seeds is that the BIP-39 error detection is not very compatible with these methods. The problem is that you want the shared seeds to have BIP-39 error detection, and ideally to have the joined seed with BIP-39 error detection, too. But that is difficult to do because BIP-39 requires 32-bit data and the error detection adds extra bits.
newbie
Activity: 8
Merit: 0
This method does work with with 2 of 3; You perform the method 3 times and divide the encryption seeds like this:

Alex: A1, A2
Bob: B1, A3
Charlie: B2, B3

IMO this is a better method that SSS. SSS relies to heavily on non standard software, must be done on a secure computer and the resulting shares are difficult to record. SSS is better suited for n of m where m is large as this method does not scale favourably; You need to create a share for each subset of m of size n, which grows exponentially as m increases.

http://users.telenet.be/d.rijmenants/en/secretsplitting.htm
https://bitcoin.stackexchange.com/a/65434/69224


Is this the correct way for 2 of 4 if S=x1+x2, x=(A to F)?

Nr1:A1,B1,C1
Nr2:A2,D1,E1
Nr3:B2,D2,F1
nr4:C2,E2,F2
newbie
Activity: 4
Merit: 0
December 30, 2017, 12:21:19 AM
#15
@nullius

Interesting!


You are right; the method does break the BIP39 checksum. However the mnemonic itself provides a sort of redundancy in that words can still be identified with misread or misspelled letters; such is the reason mnemonics are used in the first place. And of course you would double triple check S can be recreated from A and B before using the wallet; thus guaranteeing your shares are recorded correctly.


Why would electrums wordlist-independant seed version system make index arithmetic a worse idea? It would work just the same?


I think the real value in the one-time-pad scheme is that it's simple enough to be done with paper and pencil. Towards that end it makes sense to do wordlist arithmetic than bitwise XOR. There are less operations overall and thus less opportunity for error, believe me, I tried! Plus the method could be described to and executed by my Grandmother, an important consideration when she may be the benefactor of my coin and required to perform a recovery procedure in the event of my untimely death.


If you have an air-gapped computer with no malware that you can trust then maybe SSS is superior (favourable scaling) and maybe it's easier to XOR (native machine instruction). But you need a trusted computer and trusted software - difficult and expensive to ensure - even for IT professionals. And further this completely defeats the purpose of a hardware wallet because you have to enter into a computer your private key or seed to be XOR'ed or SSS'ed. A big no-no for cold storage.


It's trivial to guarantee that "you never XOR the same values with anything else"; thus the scheme is provably secure; so what's the problem? What do you mean by "it severely reduces availability"? Why do you think SSS would be safer?


The biggest problem I see with a software based solution (air-gaps, linux, XOR, /dev/urandom, easyseed, SSS, dd, Ian Coleman) is there is no standard for the method. Its right there on Ian Colemans implementation. From https://iancoleman.io/shamir39/: "There are no alternative implementations, meaning you are totally dependent on this tool if you use it. That is a dangerous situation to be in." And how can I ensure Ian's implementation is secure? How can I guarantee it will be available and secure into the future? How can I guarantee the same to my Grandmother? These are difficult questions to address and can require complex maintenance procedures to guard against software and data rot.


Thanks for the discussion. But my recommendation is - KISS - Keep It Simple!
legendary
Activity: 3024
Merit: 2148
December 30, 2017, 12:16:48 AM
#14

I am not a cryptographer, experienced or otherwise.  But that sounds fine to me—with the killer caveat that your “key” will need to have as many bits as an independent seed, so why bother?


The idea here is that this key should be pretty useless on its own, so you can create a lot of copies of it and store them in different places like cloud storage, HDD, flash drives, paper. However, I'm not sure if this key really doesn't leak information about the seeds.



I am not a cryptographer, experienced or otherwise.  But that sounds fine to me—with the killer caveat that your “key” will need to have as many bits as an independent seed, so why bother?

A better scheme may be to use a secret master seed, seed_0, run it through a KDF (as will be done anyway when your BIP39 seed is turned into a BIP32 HD wallet), and use the KDF to generate two independent seeds:  seed_1 for your real treasure cave, and seed_2 the “decoy”.  BIP39 simply takes a bag of bits as input; so you can still use easyseed(1) to turn your seed_2 “decoy” into a string of words, write it on a yellow sticky note, and “hide” it somewhere that bad guys will be allowed to find it after they begin to torture you (so it’ll be convincing) but before they torture you too much (what is your personal tolerance for being hit with a $5 wrench?).  Meanwhile, keep the words for seed_0 secret—not only that, but keep its existence secret!; and it can be used to recover both other “seeds”.


My goal was to make a system when you don't have to store the seed for "treasure cave" anywhere at all, so in your setup I would use seed_0 as my decoy seed and when the bad guys would take it from me, I'd generate my "treasure cave" seed1 from a backup copy of seed0. Does this sound good?

But I've just discovered that BIP39 passwords are kinda like an arbitrary bonus words, so the setup for linked decoy/treasure wallets can be much simpler - you can generate one list of words and two passwords - one is decoy (can be written on paper next to seed words), the other is super secret.

And yes, it's all built on assumption that bad guys don't know how many coins you have, that they are not very good at crypto and are just looking for 12-24 words written on paper and will leave as soon as they get some plausible amount of coins after making sure that they've searched everything.


P.S. interesting tool, gotta check it out later.
copper member
Activity: 630
Merit: 2614
If you don’t do PGP, you don’t do crypto!
December 29, 2017, 10:40:31 PM
#13
I was looking for a technique to store a wallet seed. Because if somebody find your seed that person can steal the bitcoins. I found a way to split the seed in two parts for cold storage.

- the technique can be use for any seed. Any number of words in the seed or dictionary. On a software or hardware wallet.
- encryption and decryption is simple and can be done with pen and paper if you want. I also made a python scrypt to encrypt (split) and decrypt (reassamble).
- Both parts contains only words and looks like an ordinary seed. No need to write a series of random characters that is error prone.
- The technique is based on the One time pad encryption.

I will show you how it's done manually. First you need a seed:
park color slice trade remove depend meadow bus clock curious where where

You create a second seed that will be use for encryption. I call that seed : "encryption seed A". It's one of the two part of the splitted seed. On electrum I use the make_seed command to generate it:
goddess clump renew require timber pitch loan bless sock hint ecology finish

To generate the second part that I call "encryption seed B". You need the dictionary file used by your wallet. Most of the time wallets are using https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt. For each words in your seed and in your "encryption seed A". You need the word number in the dictionary. The first word is number 1 and the last one is 2048.

[...]

Why are you performing modular arithmetic on wordlists, when computers think in bits?  N.b. that you will break the checksum this way.  BIP 39 stuffs 4–8 checksum bits into the last word; how many, depends on the length of the seed.  I presume you will want means to check that your seed_b is recorded correctly, without access to your seed_a or your original seed (which I will call seed_0).

Also, Electrum does not generate BIP 39 seeds.  You are mixing two different standards.  Off the top of my head, I don’t know whether Electrum uses the same English-language wordlist by default.  But I do know that Electrum’s competing Seed Version System was designed to be fully wordlist-independent, which makes wordlist-arithmetic an even worse idea.

I suggest you XOR two seed-sized values drawn off /dev/urandom, then encode the results into BIP 39 seeds.  You can do all of this except the XOR using dd(1) and easyseed(1), a secure BIP 39 seed generator which I so happen to have published yesterday (forum thread).  easyseed(1) can take a file as input, or read from stdin.  Producing the bitwise XOR of two equally-sized files is a trivial “hello, world” jobs in C, and probably in Python, too.  Also, this could be done in memory without touching disk with a tiny bit of modification to easyseed(1); or, just use a memory disk and be sure to wipe it when you’re done.

Well, that is if you want to do the scheme you said.  As HCP pointed out, SSS is really the right tool for the job here.  Your splitting scheme is secure, on condition that you never XOR the same values with anything else (see “pad reuse”).  But it severely reduces availability.  Using SSS and transforming its output to words through a secure mnemonic scheme would be much safer.  I have been mental-whiteboarding a tool based on SSS, mnemonic phrases, and some other tricks for exactly these kinds of scenarios, though it may be awhile before I actually write it.


I've too recently came up with an idea for seeds and I hope some experienced cryptographers here will tell me if it's good or not.

First, we generate seed A which is our secret seed and used to create main wallet.

Then we generate seed B, which will act as a decoy.

Then we calculate a key such as (key + seed B) mod 2048 = seed A

Seed B is used to store small portion of BTC savings, so in case someone will get access to your private storage (thieves, kidnappers or police), they will get only a small portion of your coins, while you will be able to later restore your main wallet with a backup copy of seed B and the key.

My question is, is this scheme viable, or are there better ways to do it, like having independent decoy while hiding the main wallet through other means?


I am not a cryptographer, experienced or otherwise.  But that sounds fine to me—with the killer caveat that your “key” will need to have as many bits as an independent seed, so why bother?

A better scheme may be to use a secret master seed, seed_0, run it through a KDF (as will be done anyway when your BIP39 seed is turned into a BIP32 HD wallet), and use the KDF to generate two independent seeds:  seed_1 for your real treasure cave, and seed_2 the “decoy”.  BIP39 simply takes a bag of bits as input; so you can still use easyseed(1) to turn your seed_2 “decoy” into a string of words, write it on a yellow sticky note, and “hide” it somewhere that bad guys will be allowed to find it after they begin to torture you (so it’ll be convincing) but before they torture you too much (what is your personal tolerance for being hit with a $5 wrench?).  Meanwhile, keep the words for seed_0 secret—not only that, but keep its existence secret!; and it can be used to recover both other “seeds”.


Instead of your technique OP you could just split the seed into two halfs:

seed: park color slice trade remove depend meadow bus clock curious where where
seed part 1: park color slice trade remove depend
seed part 2: meadow bus clock curious where where

part 1 and part 2 have the exact same security profile as your seed A and seed B, only that splitting and re-combining is faster.

WRONG WRONG WRONG WRONG WRONG.  As another person already told you:

Terrible advice! Do not do this! It will vastly decrease the security of your wallet!

They do not have the same security profile. Your method reveals half the information of your seed, the OP's method does not.
newbie
Activity: 4
Merit: 0
December 29, 2017, 04:02:14 PM
#12
@hatshepsut93:

Your method does seem viable. So long as your key is kept secret from the bad guys seed B will reveal no information about seed A. It reminds me of the "optional passphrase" feature of the BIP-0039 standard as described here: https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/ch05.asciidoc#optional-passphrase-in-bip-39 and here: https://blog.trezor.io/hide-your-trezor-wallets-with-multiple-passphrases-f2e0834026eb

OPs method and yours could be combined such that:

(A + B) % 2048 = S; decoy seed with small amount

and

S + "secret key passphrase"; as per BIP-0039 leads to the main wallet
newbie
Activity: 4
Merit: 0
December 29, 2017, 03:17:19 PM
#11
Terrible advice! Do not do this! It will vastly decrease the security of your wallet!

They do not have the same security profile. Your method reveals half the information of your seed, the OP's method does not. In fact it can be shown that seed A and seed B as described by OP are both random numbers and reveal absolutely no information at all.

To see this consider a simpler case where we have a three index dictionary {0, 1, 2} and our seed is only one number.

Let S be our seed chosen randomly, then:

S = 0 with 1/3 probability; S = 1 with 1/3 probability and S = 2 with 1/3 probability.

We chose A the same way:

A = 0 with 1/3 probability; A = 1 with 1/3 probability and A = 2 with 1/3 probability.

Note that since A is chosen randomly it reveals zero information about S.

B is calculated from S and A as per the scheme: B = (S - A) % 3

So consider the three cases for S:

Case: S = 0 then:

B = (S - A) % 3  = (0 - 0) % 3 = 0 with 1/3 probability (A = 0 1/3 of the time)
B = (S - A) % 3  = (0 - 1) % 3 = 2 with 1/3 probability (A = 1 1/3 of the time)
B = (S - A) % 3  = (0 - 2) % 3 = 1 with 1/3 probability (A = 2 1/3 of the time)

Case: S = 1 then:

B = (S - A) % 3  = (1 - 0) % 3 = 1 with 1/3 probability
B = (S - A) % 3  = (1 - 1) % 3 = 0 with 1/3 probability
B = (S - A) % 3  = (1 - 2) % 3 = 2 with 1/3 probability

Case: S = 2 then:

B = (S - A) % 3  = (2 - 0) % 3 = 2 with 1/3 probability
B = (S - A) % 3  = (2 - 1) % 3 = 1 with 1/3 probability
B = (S - A) % 3  = (2 - 2) % 3 = 0 with 1/3 probability


So we see no matter the value for S; B = 0 with 1/3 probability; B = 1 with 1/3 probability and B = 2 with 1/3 probability. Thus with no knowledge of A, B is indistinguishable from a random number and like A reveals zero information about S.


Your method of dividing the secret in two halves does reveal information about the seed. Consider a similar example of a four digit pin:

If I want to brute force crack the pin I have to try all combinations which is 10*10*10*10 = 10^4 = 10,000 tries. However if I discover half, I only need to crack the remaining two digits, thus I need only 10^2 = 100 tries. A factor of 100 speed up from the brute force method!





sr. member
Activity: 299
Merit: 253
December 29, 2017, 08:12:08 AM
#10
Instead of your technique OP you could just split the seed into two halfs:

seed: park color slice trade remove depend meadow bus clock curious where where
seed part 1: park color slice trade remove depend
seed part 2: meadow bus clock curious where where

part 1 and part 2 have the exact same security profile as your seed A and seed B, only that splitting and re-combining is faster.
legendary
Activity: 3024
Merit: 2148
December 29, 2017, 06:38:50 AM
#9
I've too recently came up with an idea for seeds and I hope some experienced cryptographers here will tell me if it's good or not.

First, we generate seed A which is our secret seed and used to create main wallet.

Then we generate seed B, which will act as a decoy.

Then we calculate a key such as (key + seed B) mod 2048 = seed A

Seed B is used to store small portion of BTC savings, so in case someone will get access to your private storage (thieves, kidnappers or police), they will get only a small portion of your coins, while you will be able to later restore your main wallet with a backup copy of seed B and the key.

My question is, is this scheme viable, or are there better ways to do it, like having independent decoy while hiding the main wallet through other means?
sr. member
Activity: 476
Merit: 359
December 29, 2017, 05:30:01 AM
#8
Thanks for sharing, i am still a newbie at this thing.
For now, i only use blockchain wallet, the mobile one. I do have my own seed that i write on a paper. I guess this is a modern way of a paper wallet.
May i ask something?
1. Do you run this on linux or windows?
2. What happen if you lost a part of the seed?
3. Any video on this? So i can double learn it via an intructional video.

Thanks again for sharing this, i will watch this topic maybe there will be any updates, and i still want to read it for a good lesson.
newbie
Activity: 38
Merit: 0
December 29, 2017, 05:02:53 AM
#7
Interesting
newbie
Activity: 4
Merit: 0
December 28, 2017, 02:04:52 PM
#6
This method does work with with 2 of 3; You perform the method 3 times and divide the encryption seeds like this:

Alex: A1, A2
Bob: B1, A3
Charlie: B2, B3

IMO this is a better method that SSS. SSS relies to heavily on non standard software, must be done on a secure computer and the resulting shares are difficult to record. SSS is better suited for n of m where m is large as this method does not scale favourably; You need to create a share for each subset of m of size n, which grows exponentially as m increases.

http://users.telenet.be/d.rijmenants/en/secretsplitting.htm
https://bitcoin.stackexchange.com/a/65434/69224
HCP
legendary
Activity: 2086
Merit: 4361
True... but is there a way with your example to split into 2 of 3 type shares? That would be really great if you could have the benefits of being able to use "normal" words instead of long hex strings, but still have the safety of 2of3... so if one share gets lost, you can still recover.

I think that would make your system ever better Smiley
HCP
legendary
Activity: 2086
Merit: 4361
And what happens if you lose one part of it? You cannot recover the whole thing can you?

You'd be better of using "Shamir Secret Sharing" and use a 2of3 system... so you still need at least 2 of the 3 parts to be able to reconstruct... so if one part gets compromised, you're still OK... but also, if one part gets lost, you can still recover with the other two.

Example here: http://point-at-infinity.org/ssss/demo.html
newbie
Activity: 36
Merit: 0
So it's basically a cipher? With some fancy code?
hero member
Activity: 700
Merit: 500
Thank you for posting this. I have been telling people for a while now to use paper wallets instead of storing Bitcoin on exchanges because obviously if you don't control your private keys then your Bitcoin is at risk.

With that said, this is something new which I am not technically savvy enough to understand right now. I need to research it, but will keep this post in the back of my mind in case the need to store Bitcoin in this way arises.

Again, thanks for posting this. Smiley
hero member
Activity: 637
Merit: 502
I was looking for a technique to store a wallet seed. Because if somebody find your seed that person can steal the bitcoins. I found a way to split the seed in two parts for cold storage.

- the technique can be use for any seed. Any number of words in the seed or dictionary. On a software or hardware wallet.
- encryption and decryption is simple and can be done with pen and paper if you want. I also made a python scrypt to encrypt (split) and decrypt (reassamble).
- Both parts contains only words and looks like an ordinary seed. No need to write a series of random characters that is error prone.
- The technique is based on the One time pad encryption.

I will show you how it's done manually. First you need a seed:
park color slice trade remove depend meadow bus clock curious where where

You create a second seed that will be use for encryption. I call that seed : "encryption seed A". It's one of the two part of the splitted seed. On electrum I use the make_seed command to generate it:
goddess clump renew require timber pitch loan bless sock hint ecology finish

To generate the second part that I call "encryption seed B". You need the dictionary file used by your wallet. Most of the time wallets are using https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt. For each words in your seed and in your "encryption seed A". You need the word number in the dictionary. The first word is number 1 and the last one is 2048.

seed:
Code:
park color slice trade remove depend meadow bus clock curious where where
1282 365 1627 1845 1455 471 1101 247 347 431 2002 2002

encryption seed A:
Code:
goddess clump renew require timber pitch loan bless sock hint ecology finish
801 354 1457 1464 1809 1324 1048 189 1648 862 560 696

Finally to obtain "encryption seed B" for each word you need to calculate index(word_seed) - index(word_encryption_a) % 2048.

ecryption seed B:
Code:
481 11 170 381 1694 1195 53 58 747 1617 1442 1306
destroy accident best cook stable nice allow also frost sketch reform person

Now you can write "encryption seed A" and "encryption seed B" on separate piece of paper. Before deleting you seed you should test decryption. You just need encryption seed A and B and calculate index(word_encryption_a) + index(word_encryption_b) % 2048. Now you can safely delete your seed and hide both encryption seeds in separate locations.

Here is the Python script that does the splitting and reassambly:
Code:
#!/usr/bin/python3

import sys, getopt

with open('english.txt') as file:
words = file.read().splitlines()

def validate_seed(seed):
for word in seed:
if word not in words:
print(word, 'is not a valid BIP39 word')
sys.exit(1)

def usage():
print('If you want to crypt a seed:   crypt_seed.py')
print('If you want to decrypt a seed: crypt_seed.py -d')

if len(sys.argv) == 2:
arg = sys.argv[1]
if arg in ('-h', '--help'):
usage()
elif arg in ("-d", "--decrypt"):
encryption_seed_a = input('Enter your encryption seed A: ').split()
validate_seed(encryption_seed_a)

encryption_seed_b = input('Enter your encryption seed B: ').split()
validate_seed(encryption_seed_b)

seed = ''

for i,word_a in enumerate(encryption_seed_a):
index_a = words.index(word_a)
index_b = words.index(encryption_seed_b[i])
index_seed = (index_a + index_b) % 2048
word_seed = words[index_seed]
seed += word_seed + ' '

print('Your seed is: ', seed)
else:
print('Unrecognized argument')
usage()
else:
seed = input('Enter your seed: ').split()
validate_seed(seed)

encryption_seed_a = input('Enter an encryption seed A: ').split()
validate_seed(encryption_seed_a)

encryption_seed_b = ''

for i,word_seed in enumerate(seed):
index_seed = words.index(word_seed)
index_a = words.index(encryption_seed_a[i])
index_b = (index_seed - index_a) % 2048
word_b = words[index_b]
encryption_seed_b += word_b + ' '

print('Your encryption seed B is: ', encryption_seed_b)
Jump to: