Argon2 is modern ASIC-resistant and GPU-resistant secure key derivation function. It has better password cracking resistance (when configured correctly) than PBKDF2, Bcrypt and Scrypt (for similar configuration parameters for CPU and RAM usage).
The Argon2 function has several variants:
- Argon2d – provides strong GPU resistance, but has potential side-channel attacks (possible in very special situations).
- Argon2i – provides less GPU resistance, but has no side-channel attacks.
- Argon2id – recommended (combines the Argon2d and Argon2i).
Argon2 has the following config parameters, which are very similar to Scrypt:
- password
P
: the password (or message) to be hashed - salt
S
: random-generated salt (16 bytes recommended for password hashing) - iterations
t
: number of iterations to perform - memorySizeKB
m
: amount of memory (in kilobytes) to use - parallelism
p
: degree of parallelism (i.e. number of threads) - outputKeyLength
T
: desired number of returned bytes
You can play with the Argon2 password to key derivation function online here: http://antelle.net/argon2-browser.
Now, we shall write some code in Python to derive a key from a password using the Argon2 algorithm.
First, install the Python package argon2_cffi
using the command:
pip install argon2_cffi
Now, write the Python code to calculate Argon2:
import argon2
argon2Hasher = argon2.PasswordHasher(time_cost=50, memory_cost=102400, parallelism=8, hash_len=32, salt_len=16)
hash = argon2Hasher.hash("s3kr3tp4ssw0rd")
print("Derived key:", hash)
The Argon2 calculation takes several input configuration settings: time_cost (number of iterations), memory_cost (memory to use in KB), parallelism (how many parallel threads to use), hash_len (the size of the derived key), salt_len (the size of the random generated salt, typically 128 bits / 16 bytes).
Sample output from the above code execution:
Derived key: $argon2id$v=19$m=102400,t=50,p=8$JPoIjwAPeCGiLFwdhcCMwQ$Mf9d8TtMA7b21/8VTyW+zEYlzMo2TyPclkf4qnNUzCI
Note that the above output is not the derived key, but a hash string in a standardized format, which holds the Argon2 algorithm config parameters + the derived key + the random salt. By design, the salt and the derived key should be different at each code execution.
Try to change the time_cost or the memory_cost settings and see how they affect the execution time for the key derivation.
In many applications, frameworks and tools, Argon2 encrypted passwords are stored together with the algorithm settings and salt, into a single string (in certain format), consisting of several parts, separated by $
character. For example, the password p@ss~123
can be stored in the Argon2 standard format like this (several examples are given, to make the pattern apparent):
$argon2d$v=19$m=1024,t=16,p=4$c2FsdDEyM3NhbHQxMjM$2dVtFVPCezhvjtyu2PaeXOeBR+RUZ6SqhtD/+QF4F1o
$argon2d$v=19$m=1024,t=16,p=4$YW5vdGhlcnNhbHRhbm90aGVyc2FsdA$KB7Nj7kK21YdGeEBQy7R3vKkYCz1cdR/I3QcArMhl/Q
$argon2i$v=19$m=8192,t=32,p=1$c21hbGxzYWx0$lmO1aPPy3x0CcvrKpFLi1TL/uSVJ/eO5hPHiWZFaWvY
When configured properly Argon2 is considered a highly secure KDF function, one of the best available in the industry, so you can use it as general purpose password to key derivation algorithm, e.g. to when encrypting wallets, documents, files or app passwords. In the general case Argon2 is recommended over Scrypt, Bcrypt and PBKDF2.