I'm creating a password vault and I'm planning on using Argon2id to derive the master key from the master password. For encryption I'm planning on using XChaCha20 with Poly1305. To be clear: a set of multiple passwords and usernames will be encrypted using XChaCha20 and authenticated using Poly1305, using (a random 192-bit IV and) a 256-bit key derived from a master password using Argon2id (the version that tries to both resist GPU cracking attacks and side-channel attacks) (using 256-bit secure random salt; although I might actually just use 128-bit salt because that should also be plenty). (If there's any issues with this setup, such as with using the id version of Argon2 or using XChaCha20, also tell me, but I think these should be suitable.) Eventually, I'd like to make the password vault usable on both desktop(/laptop) and mobile devices.
Now I want to determine good secure-but-not-overkill default parameters to use for Argon2id, that are both suited for modern mobile phones and normal computers. The parameters to choose are the following:
- Time cost (number of iterations)
- Memory cost (number of KiBs to use)
- Parallelism (number of threads to use; also influences the output)
The Argon2 draft RFC just tells us to first choose the maximum memory cost and parallelism you can afford and increase the time cost until the function takes longer than you can afford.
- "For interactive, online operations,
crypto_pwhash_MEMLIMIT_INTERACTIVEprovide base line for these two parameters"
- Currently this means 2 iterations and 64 MiB RAM (see crypto_pwhash_argon2id.h)
crypto_pwhash_MEMLIMIT_MODERATEcan be used"
- Currently 3 iterations and 256 MiB RAM
- "For highly sensitive data and non-interactive operations,
crypto_pwhash_MEMLIMIT_SENSITIVEcan be used"
- Currently 4 iterations and 1 GiB RAM
(In all cases just one thread is used.) A quick benchmark on my laptop tells me that the function just takes 3.9 seconds with the last set of parameters (using the original Argon2id implementation), which I think is more than acceptable because I prefer having a secure system. However, on my phone this takes 8 seconds (using argon2kt), which is a bit longer than I'd prefer, not to mention that 1 GiB is quite a lot of memory.
For reference I took a look at the source code of password vault KeePass, and it seems they use Argon2d (so less side-channel protection) with 2 iterations with just 1 MiB of memory (but 2 threads) by default: [excerpt from
internal const ulong DefaultIterations = 2; internal const ulong DefaultMemory = 1024 * 1024; // 1 MB internal const uint DefaultParallelism = 2;
It it just me, or is that a bit on the insecure side??
Also, what role does the parallelism parameter play in countering attacks? Is this not as important, as libsodium just keeps it at 1?
Concluding, I think this all is a bit vague and I'd like to have some minimum secure values for the 3 parameters, because what if I take small parameters because I just have a slow phone, while the attacker has a bunch of fast GPUs? Then my vault would be utterly useless. Also, I imagine one can also go overboard and choose values way larger than necessary; is there some limit after which directly cracking the symmetric key is faster than guessing passwords?