When I applied for the ETH Denver Hackathon, I didn’t know who I was going to be working with or what I was going to be working on. Through some mutual friends, I ultimately teamed up with Mark, Nick, and Juwon to work on a problem the three of us agreed was key to cryptocurrency adoption: seed management. Our project KeySplit was ultimately picked as one of the top 7 projects from over 130 teams at the ETH Denver Hackathon, so I decided a write-up was in order.
Cryptocurrencies allow you to be your own bank, which has a certain appeal to it. But if you forget the PIN to your bank account or lose your bank card you can go into your local branch, provide evidence of your identity, and have access to your money restored. If you lose the keys to your cryptocurrency wallet or forget the encryption password, there’s nobody in the world who can help you.
This leads many people to keep money out of cryptocurrency altogether, and many who do invest in cryptocurrency entrust it to centralized services, which often ends badly.
If you’re interseted in signing up for the KeySplit beta, check it out on keysplit.io.
For several years, most cryptocurrency wallets have been based on a concept of Hierarchical Deterministic Wallets, or HD Wallets. The basic idea with an HD Wallet is that you have one blob of securely generated random data called a “seed”. That seed is used to generate the public and private keys used to send and receive tokens. You might generate a thousand different Bitcoin or Ethereum addresses from that seed, but so long as you have the original seed you’ll be able to recover all of your keys.
This makes the seed very important. If a bad guy gets a hold of your seed, they have access to all of your cryptocurrency accounts. If you lose your seed, you’ll never be able to regenerate your keys from it. A common pattern is to encode a user’s seed as a series of words called a “mnemonic” or “seed phrase”, and have the user write down these words on a piece of paper. If your seed is on your computer and you get a virus, the virus author gets your key. If your seed is on a piece of paper in your desk drawer, they need physical access to your desk.
Having your seed on paper instead of your PC helps, but there are still risks. If your house gets robbed, a burglar might take your seed. Today many burglars might not know why I have “borrow bridge syrup expose course debris know enforce blush point exchange frown” written on a piece of paper - that sounds like nonsense - but as cryptocurrencies gain popularity it will become very obvious that’s a seed mnemonic. Additionally, if you are ever the victim of a house fire, a seed written on a piece of paper will be one of the first things to go. There are options like cryptosteel, which should survive a fire, but it’s an expensive solution for a user who isn’t heavily invested in cryptocurrency and more complicated than conventional investment solutions.
Our goal for KeySplit was to create a solution for storing HD Wallet seeds that was easy to use, inexpensive, and could survive the types of disasters that would compromise a piece of paper stored at home.
Note that this write-up reflects how KeySplit is intended to work once complete. Much of what is described here was implemented during the ETH Denver Hackathon, but our team is continuing the effort to finish the implementation.
Our goal for the user experience was this:
- A user generates a mnemonic using their wallet. The wallet may be Metamask, a Ledger Nano S, Bitcoin Core, Electrum - you name it. Any wallet that generates a bip39 compatible mnemonic should work with KeySplit.
- The user enters their mnemonic into KeySplit.
- KeySplit divides the seed into 5 shards using Shamir’s Secret Sharing Scheme. Three of the five shards are needed to reconstruct the original seed.
- KeySplit helps the user distribute the shards to 5 trusted individuals called guardians. These should be people the individual has a personal relationship with. KeySplit encourages people to pick friends from different parts of their life, both to help prevent collusion, and to help ensure that multiple guardians aren’t compromised by the same catastrophic events.
- On a regular basis KeySplit will remind users to log into KeySplit. This helps the user remember their password (which they will need if they ever need to restore their seed from shards), and also notifies the people they are acting as guardian for that they are still in possession of their shards.
- If a guardian doesn’t log in for an extended period, the people whose keys they were protecting can be notified.
- If a seed recovery is required, a user can request shards from their guardians and reconstruct the seed using KeySplit. Guardians will see the shards as mnemonics, so shards can be shared verbally if necessary.
Obviously, there are a lot of security considerations that went into KeySplit.
Splitting The Seed Securely
KeySplit uses Shamir’s Secret Sharing Scheme, which allows users to split any secret into N shards, K of which can be used to reconstruct the original secret. For KeySplit, we’ve set N = 5 and K = 3, so seeds have 5 guardians, and the seed can be reconstructed from any 3 shards. In the future we may give users the option to use different parameters; for example they may want 8 guardians and require 5 shards to reconstruct the key.
For the initial development we chose 3 of 5. Setting
K = N - 2 means we have
two shards worth of redundancy, allowing seeds to survive the loss of up to two
guardian’s shards before the seed is permanently lost. We wanted
K > 2 to
help protect against collusion (more later). This gave us a minimum of 5
shards, meaning users will need to find at least five guardians they trust to
protect their keys.
Distributing the Shards Securely
Distributing the shards securely was a particular challenge. Given some parameters of the hackathon, we were interested in using Toshi Messenger or Status Messenger, both of which offer the ability to send end-to-end encrypted messages. The problem with both of these solutions is that we would depend on the message recipient to delete the message once the shard was stored securely within KeySplit; a step which would often be skipped in practice, leaving the shard in their message history.
To simplify things, we added our own web service into the stack. The user who generates the shards encrypts the shard with a randomly generated key, then uploads it to our web service. We only get an encrypted shard, so we hold nothing that could compromise the user’s seed. Our service supplies a object ID, which can be used to retrieve the object in the future.
The client then generates links to be provided to guardians. The links are comprised of:
Putting the object-id and encryption-key after the “#” portion of the URL makes that data available to the KeySplit client application, but does not send them to the KeySplit server-side application. The KeySplit client uses the object-id to retrieve the shard from the API server, and the encryption key to encrypt the shard. Then it re-encrypts the shard with the guardian’s password, and stores it in the browser’s localStorage.
Confirming Possession of Shards
Finally, we need to notify the seed’s owner that the shard has been downloaded. To do this, we take a hash of the shard and call an Ethereum contract to log an event indicating the address that is protecting the shard. This allows the seed owner to determine if their shard has been stored without an easy way to correlate which shards correspond to which users.
The KeySplit API also monitors the Ethereum contract for confirmations that a guardian has stored a shard. Once it sees a shard confirmed, it deletes the encrypted shard from its memory, rendering the link that was probably left in a conversation window unusable.
Periodically when guardians re-authenticate with KeySplit, they will resend confirmations to indicate they still possess the shard, offering the seed owner assurances that their shards are safe should they ever need to reconstruct the seed.
Collusion Among Guardians
One risk to this approach is collusion among guardians, either voluntary or involuntary. We have several measures in place to protect against collusion.
First, in the UI we encourage people to select people from different parts of their life. We give people several different categories to choose from. Some examples are:
By choosing people from different categories, it makes it less likely that any one person would be able to determine enough guardians of a single key, and less likely that guardians would be willing to collude with eachother and betray a friend’s trust.
In addition to splitting shards among people from different parts of life, before we shard the seed we encrypt it with a key derived from the shard owner’s password. Thus, even if enough guardians colluded to reconstruct the seed, they would still need to brute force the user’s password.
One of the original problems that KeySplit was trying to solve is that humans are bad at remembering complex passwords. Encrypting the user’s seed before sharding means that the user must remember a password. KeySplit addresses this in a couple of different ways.
First, the foremost security of the system comes from the difficulty of acquiring enough shards from guardians. This means that, in general, it is not necessary for a password to match the cryptographic strength of the password it protects, thus making it easier to remember.
To help the user remember their password KeySplit will eventually support recurring reminders to log into KeySplit. Logging into KeySplit on a regular basis will serve a dual purpose of having guardians re-confirm that they possess the shards they are guarding, while also helping reinforce the user’s memory of their password.
Finally, because we do not expect users passwords to be as complex as the seeds they are protecting, we use a password-based key derivation function with many rounds to increase the complexity of brute forcing a password. The challenge here is that using a key derivation function with enough rounds to significantly hinder a determined attacker means that checking the password on a mobile device is very time consuming. For now we are using PBKDF2 with 100,000 rounds, which takes about 1 second on a typical mobile device. We are weighing options for alternative key derivation functions.
KeySplit uses a cryptography based approach to enabling account recovery using a trusted network of friends. This is useful for a wide variety of cryptocurrencies, and potentially even encryption keys used outside of blockchain technologies.
The smart contract capabilities of Ethereum provide opportunities for potentially more robust solutions, but I’ll discuss those in the next blog post.