# How to choose parameters for Argon2 for password vault

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.

Another page references multiple sources, such as the libsodium documentation, which has multiple recommendations:

• "For interactive, online operations, crypto_pwhash_OPSLIMIT_INTERACTIVE and crypto_pwhash_MEMLIMIT_INTERACTIVE provide base line for these two parameters"
• "Alternatively, crypto_pwhash_OPSLIMIT_MODERATE and crypto_pwhash_MEMLIMIT_MODERATE can be used"
• Currently 3 iterations and 256 MiB RAM
• "For highly sensitive data and non-interactive operations, crypto_pwhash_OPSLIMIT_SENSITIVE and crypto_pwhash_MEMLIMIT_SENSITIVE can 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 KeePassLib.Cryptography.KeyDerivation.Argon2Kdf:]

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?

• Minimum parameters really depends on your threat model and the machines you want to run this on. If you're actually worried about government attacks, then you need to ignore users who have slow hardware. If you want to support users with slow hardware, then you need to accept some loss in security. Unfortunately, there is no set answer for every scenario. – Aman Grewal Sep 22 '20 at 0:16