oed / seedsplit

Use shamirs secret sharing scheme to split a seed mnemonic for crypto wallets to multiple mnemonics.
MIT License
123 stars 30 forks source link

Switch to dsprenkles/sss-node (experimental) #9

Closed Shulyaka closed 6 years ago

Shulyaka commented 6 years ago

Hi,

This is a kind of experimental proof-of-concept code that you may find useful or interesting. I don't expect you to merge it right away, but rather to consider.

  1. Replaced secrets.js with dsprenkles/sss-node
  2. Currently only works with 24-word mnemonics
  3. Resolves issues #5, #7, and #8
  4. Each shard is a number followed by exactly 24 words (shorter phrases are insecure anyway)
  5. The lib/seedsplit.js functions now return a promise
  6. Shards are not backwards compatible with the current seedsplit version
Shulyaka commented 6 years ago

Example:

[denis@localhost seedsplit]$ echo "island rich ghost moral city vital ignore plastic slab drift surprise grid idea distance regret gospel page across bird obscure copy either vessel jeans" | node bin/cli.js split -t 2 -s 3
Enter seed mnemonic:  
1 pony quality biology flush middle flight universe stool like ocean climb casino super buyer smooth owner hidden gravity unable hunt mass media early borrow
2 sorry earn angry best glide purpose chat grant fox wall lawsuit such liquid wrong chimney raven husband boss grass inject they special warm shuffle
3 bus farm lecture segment shiver adjust rookie beyond blade clutch monster output clog taxi expect embrace omit lazy palace lobster fix budget donate rebel
[denis@localhost seedsplit]$ node bin/cli.js combine -t 2
Enter shard mnemonic:  1 pony quality biology flush middle flight universe stool like ocean climb casino super buyer smooth owner hidden gravity unable hunt mass media early borrow
Enter shard mnemonic:  3 bus farm lecture segment shiver adjust rookie beyond blade clutch monster output clog taxi expect embrace omit lazy palace lobster fix budget donate rebel
island rich ghost moral city vital ignore plastic slab drift surprise grid idea distance regret gospel page across bird obscure copy either vessel jeans
oed commented 6 years ago

Hey @Shulyaka, this is really cool!

  1. How come this only works for 24 word seeds?
  2. I don't really have a problem with there being a number in front of the share seed. Seems like a totally fine tradeof!
  3. Very nice :D
  4. I think that's fine. Just need to make sure that the documentation says clearly that a breaking change was made. People who need it can just use the old version.
Shulyaka commented 6 years ago

24 words - this is the limitstion of sss-node's keyshares API, it only works with 32-byte keys. And I couldn't find a good way to use it for shorter keys.

oed commented 6 years ago

@Shulyaka ok, and I suppose there is no way that we can pad a shorter secret?

Shulyaka commented 6 years ago

I couldn't find a good way to do it. All my ideas would result with a much longer shares than initial seed.

Here is what I have found out:

  1. In its core the sss-node library is only capable of operating with 256-bit keys. This is not something that can be easily fixed, it is tied very deep into the design, to enable a different key length the whole code responsible for the actual Shamir algorithm will have to be rewritten. The most interesting part is in the header and in sss_create_keyshares() function of sss/hazmat.c file, which implement the sss itself.
  2. It provides two sets of APIs: keyshare API for 256-bit keys that return 8+256 bit shares, and normal API for arbitrary-length data. The latter generates a random 256-bit key which is used to encrypt the data. The key is split by the mentioned sss_create_keyshares() function into key shares. The result of the API (i.e. the data shares) is the key share with the encrypted data. That would be 36 mnemonic words (12 for the encrypted text + 24 for the key) for a 12-word initial seed (plus a number) if we use this "normal API". May be even more, if encrypted data length is bigger than the clear data. You can find the code in sss.c file.
  3. 24-word mnemonic generates a 256-bit key an 12-word mnemonic generates a 128-bit key. There might be other ways to get a 256-bit key from a 128-bit one. But it has to be distinguishable from a real 256-bit key that was generated from a 24-word mnemonic. And if we add any more bytes to it to indicate a length, that would be greater than 256 bits requiren for the keyshare API.

I hope my explanation is not too complicated. Please also see the libraries' technical details and my issue that I raised to clarify the above points.

I believe, the real question here is whether you want to support shorter (unsecure) mnemonics in the future. And if you do, may be it is better to stick to the current library.

oed commented 6 years ago

Thanks for the writeup! I guess one simple thing that could be done is the following:

  1. take 128-bit key from the 12-word seed and concatenate with 128 random bits
  2. split the above data to generate n 24-word shares
  3. each shard starts with s<number> instead of just a number

24-word seeds could be encoded with l<number>. Now when recovering l means that it's a "long" seed and s that it's a "short" seed.

Shulyaka commented 6 years ago

Ok, will try to implement something like this

oed commented 6 years ago

Awesome, thanks!

Shulyaka commented 6 years ago

Well, it is done now, please check.

I found out that apart from 128 bit and 256 bit mnemonics, there can also be 160 bit, 192 bit, and 224 bit. I have assigned the following prefixes: x for 128bit (12 words, "eXtra short") s for 160bit (15 words, "short") t for 192bit (18 words, "tiny") m for 224bit (21 words, "moderate") No prefix for native 256bit (24 words) Please advise if you prefer "a b c d" prefixes or something like this

Each share has 24 words regardless of original size.

Example:

[denis@localhost seedsplit]$ echo "leave culture supreme spider sport speak globe banner obey rhythm rubber tumble pact erupt piece" | node bin/cli.js split -t 2 -s 3
Enter seed mnemonic:
s1 girl arrow wagon debris family penalty exercise afford replace orient liar raw home twist hotel relief cherry render lucky miracle subway spare wing usage
s2 effort panther scale curtain glass rich firm buddy stick weasel dragon fossil keep action food alien glory you thing club kingdom cream atom remain
s3 foam plunge use that tissue slam kitten area virus system lawn add media planet mule filter game mask lake erupt begin basic lunch elevator
[denis@localhost seedsplit]$ node bin/cli.js combine -t 2
Enter shard mnemonic:  s1 girl arrow wagon debris family penalty exercise afford replace orient liar raw home twist hotel relief cherry render lucky miracle subway spare wing usage
Enter shard mnemonic:  s3 foam plunge use that tissue slam kitten area virus system lawn add media planet mule filter game mask lake erupt begin basic lunch elevator
leave culture supreme spider sport speak globe banner obey rhythm rubber tumble pact erupt piece
oed commented 6 years ago

Nice, I'm going to merge this against the develop branch. I have some stylistic changes that I would like to make. I think I'll go for the a, b, c, ... prefixes. When I make a new PR against the master branch tagging a new release, I'll ping you :)

Shulyaka commented 6 years ago

Great!

Please keep shards for 24 words without prefixes (just a number), that's my personal wish:)

oed commented 6 years ago

Why do you want that? For me it would make more sense to be consistent. It also simplifies the code.

Shulyaka commented 6 years ago

That's my use case for the tool. I plan to split the seed from my hardware crypto wallet into pieces and put them into a cold storage device like billfodl or cryptosteel, and hand them over to some members of my family and some friends. Because they are designed to store only 24 words, the share number will have to be remembered, possibly for many years. And remembering a single digit is much more convenient and reliable than, say, 'd3'. I am sure I am not the only one who could benefit from a little more convenience, and 24-word shards a going to be most common.

oed commented 6 years ago

Thanks, I'll keep that as is then.