86 lines
3.3 KiB
Plaintext
86 lines
3.3 KiB
Plaintext
_section: Security @<security>
|
|
|
|
_subsection: Key Derivation Functions @<security--pbkdf>
|
|
|
|
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](link-wiki-scrypt),
|
|
which is a memory and CPU intensive algorithm which computes
|
|
a key (fixed-length pseudo-random series of bytes) for a given
|
|
password.
|
|
|
|
|
|
_heading: 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 compuers,
|
|
increasing the cost to [brute-force attack](link-wiki-bruteforce)
|
|
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.
|
|
|
|
_heading: 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.
|
|
|
|
_heading: 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.
|
|
|
|
_code: @LANG<javascript>
|
|
|
|
// 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
|
|
}
|
|
});
|