Key Derivation Functions

This is not specific to Ethereum, but is a useful technique to understand and has some implications on User Experience.

Many people are concerned that encrypting and decrypting an Ethereum wallet is quite slow and can take quite some time. It is important to understand this is intentional and provides much stronger security.

The algorithm usually used for this process is scrypt, which is a memory and CPU intensive algorithm which computes a key (fixed-length pseudo-random series of bytes) for a given password.

Why does it take so long?

The goal is to use as much CPU and memory as possible during this algorithm, so that a single computer can only compute a very small number of results for some fixed amount of time. To scale up an attack, the attacker requires additional computers, increasing the cost to brute-force attack to guess the password.

For example, if a user knows their correct password, this process may take 10 seconds for them to unlock their own wallet and proceed.

But since an attacker does not know the password, they must guess; and each guess also requires 10 seconds. So, if they wish to try guessing 1 million passwords, their computer would be completely tied up for 10 million seconds, or around 115 days.

Without using an algorithm like this, a user would be able to log in instantly, however, 1 million passwords would only take a few seconds to attempt. Even secure passwords would likely be broken within a short period of time. There is no way the algorithm can be faster for a legitimate user without also being faster for an attacker.

Mitigating the User Experience

Rather than reducing the security (see below), a better practice is to make the user feel better about waiting. The Ethers encryption and decryption API allows the developer to incorporate a progress bar, by passing in a progress callback which will be periodically called with a number between 0 and 1 indication percent completion.

In general a progress bar makes the experience feel faster, as well as more comfortable since there is a clear indication how much (relative) time is remaining. Additionally, using language like "decrypting..." in a progress bar makes a user feel like there time is not being needlessly wasted.

Work-Arounds (not recommended)

There are ways to reduce the time required to decrypt an Ethereum JSON Wallet, but please keep in mind that doing so discards nearly all security on that wallet.

The scrypt algorithm is designed to be tuned. The main purpose of this is to increase the difficulty as time goes on and computers get faster, but it can also be tuned down in situations where the security is less important.

// Our wallet object const wallet = Wallet.createRandom(); // The password to encrypt with const password = "password123"; // WARNING: Doing this substantially reduces the security // of the wallet. This is highly NOT recommended. // We override the default scrypt.N value, which is used // to indicate the difficulty to crack this wallet. const json = wallet.encrypt(password, { scrypt: { // The number must be a power of 2 (default: 131072) N: 64 } });