During some random come-get-free-food party with Jeff at DevCon4, we discussed a technique that would allow Ethereum (as well as most other crypto-currencies) to easily recover the majority of user accounts in the event of a quantum computer attack, migrating to quantum-secure algorithms (such as lamport signatures).
I've been promising to get a little article together to explain this, and so here we are. This article will outline a hypothetical migration path that the Ethereum community could follow to rescue the network from quantum computers.
tl;dr: prove you own the account mnemonic phrase, not the private key
It is important to understand, that while quantum computers can perform a certain class of problems very efficiently, for most problems they provide very little to no advantage.
The two classes of problems we care about are:
- Elliptic Curve Cryptography, which uses a one-way operation to create a public key from a private key; knowing the public key does not allow you to compute the private key, but knowing the private key does allow you to compute the public key
- Cryptographic Hash Functions, which create a one-way mapping between a piece of data (called a "pre-image") to a digest; knowing the digest does not allow you to compute the pre-image, but knowing the pre-image does allows you to compute the digest
When an Ethereum account makes a transaction, the account's private key is used to compute a signature, which is included in the the transaction. A signature implicitly reveals the public key, which is used to verify the transaction.
Quantum computers are excellent at breaking this one-way relationship, allowing them to compute the private key from a public key.
On a post-quantum Earth, this would mean once an account has been used, even once, that anyone could compute the private key, and would gain control over all its funds, assets and permissions.
Keep in mind there is no way to distinguish between two people that each know the private key, regardless of whether they were the person that created it, or they simply acquired it later on. This is what we want to solve.
Cryptographic hash functions are absolutely amazing. They are used for a huge variety of things in the blockchain universe, and have an almostridiculous number of possibilities.
More importantly (for the purpose of this article), quantum computers provide nearly no benefit to breaking the one-way relationship. Even a quantum computer cannot compute the pre-image for a given digest (in any practical sense, at least; more below).
The focus of cryptographic hash functions today, is the method in which most wallet software and libraries generate private keys using them.
If you have ever used a crypto-currency wallet, you have likely had to write down something like a "12 word mnemonic backup phrase". If you have, this technique will work for you, since that mnemonic is basically just hashed many times in a very specific way to generate your private key.
Another powerful use case for cryptographic hash functions is "blinding".
Blinding allows us to prove at a future date that we had access to a piece of data in the past, without revealing the actual data until the future date.
For example, imagine you travelled back in time to the summer of 1995, after the airing of "Who Shot Mr. Burns: Part 1" and you wished to eventually prove you knew in advance who attempted the murder of the sun-blotting antagonist, without actually revealing who.
[ SPOILER ALERT: If you are 24-or-so years behind in Simpsons... ]
You would choose some random salt (let's say "0x614ea47..."). Then you could compute the cryptographic hash of the pre-image: "maggie shot mr burns 0x614ea47...", then share the digest with all your friends. They cannot compute the pre-image from the digest, so they cannot know what your message was.
Then after the airing of Part 2, you could reveal the pre-image, allowing them to compute the cryptographic hash of "maggie shot mr burns 0x614ea47..." themselves, for which they would get the same digest you committed to, proving you knew in advance, without having spoiling the surprise.
A quick note about the salt, which is that it is necessary to prevent guessing. Otherwise, your friends could simply try every possible character, checking the cryptographic hash of "smithers shot mr burns", "bumblebee man shot mr burns", and so on, until they found a hash that matched.
This is just an example of a hypothetical outline of the steps required, but let us imagine that tomorrow it is made public that quantum computers exist, and are being used to abscond with all the ethers in the 'verse.
Ultimately, what we want to achieve is to prove we have access to the private key's pre-image, which came from the mnemonic backup phrase, which proves that we actually created the account, and did not just tease it out from old transactions on the blockchain.
Using a hard fork, we would freeze the network at some block height, locking up the balances of all externally owned accounts to a known mostly-untampered-with state, and force users to upgrade to a quantum-secure account. Contract addresses do not have an associated public key, so they are already safe.
To Ethereum we would add two new operations:
commitPrivateKeyPreImage(blindedCommit, newAddress)revealPrivateKeyPreImage(preImage, salt)
Then each user would compute their blinded commit (from their mnemonic backup phrase's pre-image and a salt), and generate a new quantum-secure account address.
Calling commitPrivateKeyPreImage creates a tentative link from the legacy vulnerable Ethereum account to the new quantum secure account, but without revealing the pre-image of the private key or the salt.
Any attacker may know the private key (since they can use their quantum computer to calculate it from any old transactions the account has sent), but cannot know the pre-image that went into creating the private key in the first place, since it was generated from a cryptographic hash function.
After waiting a safe number of blocks, the user would then call revealPrivateKeyPreImage, where they reveal the pre-image and salt. Ethereum can compute the digest, and locate the tentative link, finalizing it, since the account owner has proved they had access to the original mnemonic, and not merely the private key.
At this point it is too late for an attacker to attempt to submit their own blinded commit with the revealed pre-image and their own salt because there is an older, confirmed commit.
The account is now secure and the user may go on accessing the legacy account's ether, tokens and interact with any contracts using the new quantum-secure account.
Note: Legacy contracts would require msg.sender and tx.origin preserve the legacy address; also deploying new contracts would need to check the legacy address, in case something that looked like an EOA (because it had no code) was actually an undeployed contract.
There is a bit we glossed over that is necessary to handle the BIP-32 derivation from the mnemonic phrase.
The cryptographic hash involved is actually a nested cryptographic hash, using the SHA2-512 cryptographic hash function, wrapped with another algorithm called HMAC. Together this is called HMAC-SHA2-512, which is resistant to even some of the more advanced quantum computer techniques.
The BIP-32 derivation of a given public key requires the the public key of its parent node, as well as a chain code from its parent. So, we can use these two values together to concisely describe the pre-image and as an implicit salt.
We create two functions; one that generates commit messages and reveal messages, and one that validates commit messages.
Now we can use getReveal to generate a commit message we could send to the blockchain:
Then in a later block, we can send the parent public key and chain code, which is used to generate the pre-image and as a salt, which the blockchain can then use verifyCommit.
At this point the blockchain can now safely transfer ownership of the legacy address to the new account.
I expect this will be largely unnecessary, since the upcoming account abstraction will make it much easier to switch accounts in-protocol and I hope to see on-chain contract wallets to become the norm, which have other interesting solutions. Also, quantum computers aren't likely to be a problem anytime soon. This was more of a thought experiment.
Also, this makes a semi-compelling argument to include SHA2-512 and HMAC-SHA2-512 opcodes (or precompiles) in the EVM, which would allow for interesting BIP-032 integration on-chain, such as computing addresses from extended public keys.
Anyways, any and all feedback is welcome, and if you'd like to keep up-to-date with my random projects and ramblings, follow me on twitter or GitHub.
*smile emoji*
I imagine comments pointing out issues with this will crop up. I will keep this section updated as interesting food-for-thought is mentioned. I'll start with some concerns I have myself. :o)
- This really only works well in the event we know that there are active quantum computers attacking; if the attacker keeps things quiet and rations their pilfering we would not know to enact this procedure
- There wold be a bit more effort required to think through the best way to pay the gas to call
commitPrivateKeyPreImageandrevealPrivateKeyPreImagewithout opening new DoS attack vectors - Revealing the private key and chain code of an HD node allows all other sibling nodes (and non-hardened relatives) to be computed; if the private key can be computed from the public key, then revealing the parent public key also reveals the parent private key, so some form of massive migration may be necessary, especially for UTXO-based chains, such as Bitcoin, which make heavy use of ancestor nodes