Argon2

Argon2는 2015년 7월 암호 해싱 대회에서 우승작으로 선정된 키 유도 함수이다. 설계자는 룩셈부르크 대학교의 Alex Biryukov, Daniel Dinu, Dmitry Khovratovich이다. Argon2의 참조 구현체는 크리에이티브 커먼즈 CC0(퍼블릭 도메인) 또는 아파치 라이선스 2.0으로 배포되며 이와 관련된 3개의 버전을 제공한다:
이 모드 3개는 모두 3개의 통제 변수를 사용한다:
알고리즘.
 Function Argon2
 Inputs:
 password (P): Bytes (0..232-1) Password (or message) to be hashed
 salt (S): Bytes (8..232-1) Salt (16 bytes recommended for password hashing)
 parallelism (p): Number (1..224-1) Degree of parallelism (i.e. number of threads)
 tagLength (T): Number (4..232-1) Desired number of returned bytes
 memorySizeKB (m): Number (8p..232-1) Amount of memory (in kibibytes) to use
 iterations (t): Number (1..232-1) Number of iterations to perform
 version (v): Number (0x13) The current version is 0x13 (19 decimal)
 key (K): Bytes (0..232-1) Optional key (Errata: PDF says 0..32 bytes, RFC says 0..232 bytes)
 associatedData (X): Bytes (0..232-1) Optional arbitrary extra data
 hashType (y): Number (0=Argon2d, 1=Argon2i, 2=Argon2id)
 Output:
 tag: Bytes (tagLength) 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 ℋ (but doesn't document what ℋ is). 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) ∥ Password
 ∥ Length(salt) ∥ salt
 ∥ Length(key) ∥ key
 ∥ Length(associatedData) ∥ associatedData
 H0 ← Blake2b(buffer, 64) "//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(memorySizeKB, 4*parallelism)
 Allocate two-dimensional array of 1 KiB blocks (parallelism rows x columnCount columns)
 columnCount ← blockCount / parallelism; //In the RFC, columnCount is referred to as q
 Compute the first and second block (i.e. column zero and one ) of each lane (i.e. row)
 for i ← 0 to parallelism-1 do for each row
 Bi[0] ← Hash(H0 ∥ 0 ∥ i, 1024) "//Generate a 1024-byte digest"
 Bi[1] ← Hash(H0 ∥ 1 ∥ i, 1024) "//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 (See section 3.4)
 i′, j′ ← GetBlockIndexes(i, j) //the GetBlockIndexes function is not defined
 Bi[j] = G(Bi[j-1], Bi′[j′]) //the G hash function is not defined
 Further passes when iterations &gt; 1
 for nIteration ← 2 to iterations do
 for i ← 0 to parallelism-1 do for 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 (See section 3.4)
 i′, j′ ← GetBlockIndexes(i, j)
 if j == 0 then
 Bi[0] = Bi[0] xor G(Bi[columnCount-1], Bi′[j′])
 else
 Bi[j] = Bi[j] xor G(Bi[j-1], Bi′[j′])
 Compute final block C as the XOR of the last column of each row
 C ← B0[columnCount-1]
 for i ← 1 to parallelism-1 do
 C ← C xor Bi[columnCount-1]
 Compute output tag
 return Hash(C, tagLength)