Using Shamir Secret Sharing in Ardor
The Ardor and Nxt blockchain products use what BCNext, the developer of the first Nxt release, used to call a “Brain Wallet.” What he meant was that a single hard to crack passphrase (with 128 bits of entropy or more) is used to protect your account. The account private and public keys and the account address are all derived from this single passphrase.
Anyone holding the account passphrase can submit transactions from the account. If the passphrase is lost, the funds in the account are lost forever. If the passphrase is compromised, the attacker can steal all the funds.
Faced with these initial risks, we built several layers of protection into Ardor and Nxt. Let’s review them first. Then, I’ll explain an innovative application of cryptography that can be used to secure the passphrases themselves for enterprise and/or mainstream use.
Signing transactions can be done locally inside the client browser when connected to a remote node. It works like this: the wallet submits the transaction by sending the transaction data and the account public key to a remote node. The remote node composes the transaction bytes after performing the necessary validations and returns the unsigned bytes to the browser. The browser parses the transaction bytes and validates that they indeed represent the transaction data it submitted to the remote node, then signs the transaction using the account passphrase and broadcasts the signed transaction bytes/json to the remote node.
Local signing works remarkably well as long as you download the wallet itself from an honest node. It does not protect against downloading the wallet from a compromised node or a phishing site, which will likely just modify the wallet code directly bypassing any protections.
It goes further, if you are not sure your browser is not compromised, you can perform the actual transaction signing using an offline device by scanning a QR code of the unsigned transaction bytes, signing it, and sending the transaction signature back to the online workstation to be broadcast. But then again, if your wallet is compromised, perhaps someone is able to generate a malicious QR code sending you malicious transaction bytes to the offline device to sign.
Most blockchain protocols support similar variations of transaction signing, but what is common to all of them is that at some point a single passphrase or private key has to be revealed to sign the transaction.
However, power users cannot just keep their passphrase locally all the time. Essential uses of the passphrase include signing blocks when forging, and submitting transactions automatically from batch processes like bundling, shuffling, account monitoring and running contracts. For these functions, the passphrase has to be kept on the remote node or submitted to the remote node after each restart to trigger these processes.
Faced with these risks, you might choose to store your funds on an exchange. But we know how secure this is. Exchanges with their large crypto reserves are always a lucrative target for hackers much more so than a single user.
Can we secure the passphrase itself?
It turns out that we can and it’s not even too difficult. On November 1979, MIT Cryptography Professor Adi Shamir, also known as the “S” in RSA (the first public key encryption protocol), published an iconic article named “How to Share a Secret”. In this article he introduced a (relatively) simple method for protecting private keys, known as SSS. Unlike many of the newer cryptographic protocols, the math behind this elegant idea is rather simple.
Like almost any other cryptographic algorithm, SSS also translates the problem into mathematics. We know that between two points there is only one straight line. Therefore, if we choose three points on the same line, any two of these points can reproduce the line - providing the scaffolding for a 2 out of 3 secret sharing. Using the same principals and using higher degree polynomials, we can easily extend this to any “k” pieces out of a total of “n” pieces generated from a given passphrase.
Given SSS, all we need to do is somehow convert the existing account passphrase into an integer number, which of course can be very long, then feed it into SSS to generate three secrets, which are roughly the same length, any two of them can reproduce the original passphrase, but one alone is useless.
To reproduce the passphrase, we feed any two of the secrets into SSS to receive back the numeric representation of the passphrase, which we then convert back to the original passphrase.
Assuming you split your passphrase into three pieces you can use it as follows:
- Client side redundancy — place one piece in cold storage, one in a password manager, and the 3rd stored in your wallet account settings. Instead of typing, or more likely copy/pasting the whole passphrase, you would need to only copy/paste the piece from the password manager. The browser will internally combine this with the piece in its account settings and into the original passphrase before using it. This protects against key loggers and copy/paste buffer exploits since an attacker would also need to compromise the browser’s local storage to get the 2nd piece. Additionally, if you lose one of the pieces, for example due to a disk failure, you can still use the 3rd one from the cold storage to reproduce the passphrase.
- Node security — place one piece in cold storage, one in a password manager, and the 3rd stored in your node’s configuration file. Instead of submitting the whole passphrase to the server, you can now submit only the piece from the password manager. The node itself will combine this piece with the one in its configuration to reproduce the passphrase. This protects against eavesdropping of your communication and against exploits that access your remote node file system without taking full control of your node itself.
But remember, if an attacker takes full control of your node or tricks you into connecting to a malicious remote node, no amount of cryptography or advanced architecture can help.
- Internally, Ardor and Nxt derive the 256 bit account private/public keys from the passphrase. The account address is derived from the first 64 bit of the SHA256 hash of the public key converted using Reed-Solomon error correction code into the familiar ARDOR-* and NXT-* addresses.
- Conversion between a 12-word passphrase generated by the wallet into the 128 bit random number from which it was generated can be done using a reverse lookup of the indexes in the original words array. If instead you use a randomly generated character string passphrase, it can still be converted to a number, albeit much longer one. Either way, SSS of 2/3 can be used efficiently.
For example, using the 12 words passphrase: trail rather enter mass radio confuse jeans mix relax talk cease scary the word trail has index 931 in the 1626 words array. The resulting 12 array positions are concatenated in a special way to form the 128 bit number 24464197503848153035650162909985934977 from which the three secret pieces are derived and converted back to 12 words passphrase pieces. Any two of these pieces can reproduce the original passphrase.