Argon2

**Argon2**는 2015년 7월 암호 해싱 대회에서 우승작으로 선정된 키 유도 함수이다."Password Hashing Competition"url=https://eprint.iacr.org/2016/104.pdf 설계자는 룩셈부르크 대학교의 Alex Biryukov, Daniel Dinu, Dmitry Khovratovich이다.Argon2: the memory-hard function for password hashing and other applications, Alex Biryukov, et al, October 1, 2015 Argon2의 참조 구현체는 크리에이티브 커먼즈 CC0(퍼블릭 도메인) 또는 아파치 라이선스 2.0으로 배포되며 이와 관련된 3개의 버전을 제공한다: * Argon2d: GPU 크래킹 공격의 저항성을 극대화한다. * Argon2i: 사이드 채널 공격 저항에 최적화되어 있다. 암호와 독립된 순서로 메모리 배열에 접근한다. * Argon2id: 하이브리드 버전. 메모리 처음 절반을 Argon2i이 접근하고 이후 패스는 Argon2d가 접근한다. 이 모드 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 > 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)