Algorithms

Argon2i

Argon2 with memory reads that never depend on the password. Side channels get nothing and it needs more passes for it
IDargon2i37 / 38Argon2 · variable
Hash / Password

Argon2i

Argon2 whose reads never depend on the password.

Digest
keyLength you pick
HMAC
no key mode
Security
Its reads leak nothing to a side channel
Family
3 in Argon2
8 options, 0 required

Sample

hex
246f587d8d8388b42be2b582ac49feec952f7172eea69b193daf293326f3ea50
base64
JG9YfY2DiLQr4rWCrEn+7JUvcXLuppsZPa8pMybz6lA=

Options

encodingstring
default hex
Output encoding: hex, base64, base64url, binary
saltstring
optional
Salt in hex; 32 random bytes when omitted
memorynumber
default 65536
Memory in KiB, at least 8 per lane
iterationsnumber
default 3
Passes over the memory
parallelismnumber
default 4
Lanes
keyLengthnumber
default 32
Output key length in bytes, at least 4
secretstring
optional
Secret key in hex, a pepper
associatedDatastring
optional
Associated data in hex

Access

Createcreate("argon2i")
CLIhashes argon2i 'hello world' --salt 73616c7473616c74 --memory 1024 --iterations 2 --parallelism 1
Tryplayground with the sample above
Kinargon2id, argon2d

argon2i picks every block it reads from a counter, never from the password. Somebody timing your cache learns nothing. The price? It trades memory for time more willingly, so RFC 9106 says it makes more passes to make up for it. Three passes is about right for most memory sizes, by the RFC's own math.

ts
create("argon2i").hash("password", {
  salt: "73616c7473616c74",
  memory: 1024,
  iterations: 2,
  parallelism: 1,
}).digest;
// "51d1ed13365c7dd42d6cfaefa4c1efe10eb7196a44ed4069a0486d308a93610d"

Same password, same salt, same cost as the argon2id example. A different digest anyway, because the variant goes into the very first hash. Mix them up and nothing will ever match.

Options, defaults and the byte function argon2i from @agntn/hashes/argon2 work exactly like on the argon2id page. Starting something new? Take argon2id. The RFC does too.