Argon2d maximizes resistance to GPU cracking attacks. It accesses the memory array in a password dependent order, which reduces the possibility of time–memory trade-off attacks, but introduces possible side-channel attacks.
Argon2i is optimized to resist side-channel attacks. It accesses the memory array in a password independent order.
Argon2id is a hybrid version. It follows the Argon2i approach for the first half pass over memory and the Argon2d approach for subsequent passes. The Internet draft recommends using Argon2id except when there are reasons to prefer one of the other two modes.
All three modes allow specification by three parameters that control:
execution time
memory required
degree of parallelism
Cryptanalysis
While there is no public cryptanalysis applicable to Argon2d, there are two published attacks on the Argon2i function. The first attack is applicable only to the old version of Argon2i, while the second has been extended to the latest version The first attack shows that it is possible to compute a single-pass Argon2i function using between a quarter and a fifth of the desired space with no time penalty, and compute a multiple-pass Argon2i using only / < /2.71 space with no time penalty. According to the Argon2 authors, this attack vector was fixed in version 1.3. The second attack shows that Argon2i can be computed by an algorithm which has complexity O) for all choices of parameters , , and thread-count such that =∗. The Argon2 authors claim that this attack is not efficient if Argon2i is used with three or more passes. However, Joël Alwen and Jeremiah Blocki improved the attack and showed that in order for the attack to fail, Argon2i 1.3 needs more than 10 passes over memory.
Algorithm
Function Argon2 Inputs: password : Bytes Password to be hashed salt : Bytes Salt parallelism : Number Degree of parallelism tagLength : Number Desired number of returned bytes memorySizeKB : Number Amount of memory to use iterations : Number Number of iterations to perform version : Number The current version is 0x13 key : Bytes Optional key associatedData : Bytes Optional arbitrary extra data hashType : Number Output: tag: Bytes The resulting generated bytes, tagLength bytes long Generate initial 64-byte block H0. All the input parameters are concatenated and input as a source of additional entropy. Errata: RFC says H0 is 64-bits; PDF says H0 is 64-bytes. Errata: RFC says the Hash is H^, the PDF says it's ℋ. It's actually Blake2b. Variable length items are prepended with their length as 32-bit little-endian integers. buffer ← parallelism ∥ tagLength ∥ memorySizeKB ∥ iterations ∥ version ∥ hashType ∥ Length ∥ Password ∥ Length ∥ salt ∥ Length ∥ key ∥ Length ∥ associatedData H0 ← Blake2b //default hash size of Blake2b is 64-bytes Calculate number of 1 KB blocks by rounding down memorySizeKB to the nearest multiple of 4*parallelism kibibytes blockCount ← Floor Allocate two-dimensional array of 1 KiB blocks columnCount ← blockCount / parallelism; //In the RFC, columnCount is referred to as q Compute the first and second block of each lane for i ← 0 to parallelism-1 dofor each row Bi ← Hash //Generate a 1024-byte digest Bi ← Hash //Generate a 1024-byte digest Compute remaining columns of each lane for i ← 0 to parallelism-1 do//for each row for j ← 2 to columnCount-1 do//for each subsequent column //i' and j' indexes depend if it's Argon2i, Argon2d, or Argon2id i′, j′ ← GetBlockIndexes //the GetBlockIndexes function is not defined Bi = G //the G hash function is not defined Further passes when iterations > 1 for nIteration ← 2 to iterations do for i ← 0 to parallelism-1 dofor each row for j ← 0 to columnCount-1 do//for each subsequent column //i' and j' indexes depend if it's Argon2i, Argon2d, or Argon2id i′, j′ ← GetBlockIndexes if j 0 then Bi = Bi xor G else Bi = Bi xor G Compute final block C as the XOR of the last column of each row C ← B0 for i ← 1 to parallelism-1 do C ← C xor Bi Compute output tag return Hash
Variable-length hash function
Argon2 makes use of a hash function capable of producing digests up to 232 bytes long. This hash function is internally built upon Blake2. Function Hash Inputs: message: Bytes Message to be hashed digestSize: Integer Desired number of bytes to be returned Output: digest: Bytes The resulting generated bytes, digestSize bytes long Hash is a variable-length hash function, built using Blake2b, capable of generating digests up to 232 bytes. If the requested digestSize is 64-bytes or lower, then we use Blake2b directly ifthen return Blake2b //concatenate 32-bit little endian digestSize with the message bytes For desired hashes over 64-bytes, we use Blake2b to generate twice the number of needed 64-byte blocks, and then only use 32-bytes from each block Calculate the number of whole blocks r ← Ceil-1; Generate r whole blocks. Initial block is generated from message V1 ← Blake2b; Subsequent blocks are generated from previous blocks for i ← 2 to r do Vi ← Blake2b Generate the final block partialBytesNeeded ← digestSize – 32*r; Vr+1 ← Blake2b Concatenate the first 32-bytes of each block Vi
Let Ai represent the lower 32-bytes of block Vi return A1 ∥ A2 ∥... ∥ Ar ∥ Vr+1