The Password Hashing Competition
2013-2015. Submissions: 24 entries; 9 finalists (Argon2, battcrypt, Catena, Lyra2, Makwa, Parallel, POMELO, Pufferfish, yescrypt). Selection criteria: memory-hardness against ASIC attackers, resistance to side channels (timing, cache), simplicity, and parameter flexibility.
Argon2 won in 2015. It has three modes:
- Argon2d: data-dependent memory access. Strongest against time-memory trade-off attacks, vulnerable to cache-timing side channels.
- Argon2i: data-independent. Cache-timing safe, weaker against TMTO.
- Argon2id: hybrid. First half data-independent (safe to run in shared-memory environments), second half data-dependent (resistance to TMTO). The recommended default for password hashing.
Argon2id internals
Parameters: time cost t, memory cost m (KiB), parallelism p. The algorithm:
- Initialize a memory matrix of
mKiB, sized asplanes bym/pblocks. - Fill the matrix by running BLAKE2b-based compression in a graph of dependencies. First pass uses a data-independent access pattern (each block's predecessors are deterministic). Subsequent passes use data-dependent access (next block index derived from the previous block's content).
- Repeat for
tpasses total. - Final output: hash the last block of each lane and combine.
Memory-hardness intuition: any attacker computing the output must allocate the full m KiB or trade massive computation for less memory. ASICs gain little because RAM is expensive to provision in parallel.
OWASP recommended parameters as of 2024: m=19 MiB, t=2, p=1 for low-end servers; m=47 MiB, t=1, p=1 where you can afford it. Tune so each hash is 250 to 500 ms on the slowest production server.
OPAQUE: passwords without sending them
OPAQUE (Jarecki, Krawczyk, Xu, 2018; CFRG draft) is an aPAKE (asymmetric password-authenticated key exchange). The client never sends the password to the server, even hashed. Instead:
- Registration: client and server jointly compute an Oblivious Pseudorandom Function (OPRF) over the password. Server stores an envelope and an OPRF key; the client's password never leaves their device.
- Login: client and server perform the OPRF again to derive a shared key, then run a key-exchange (HMQV-style) authenticated by that key.
Properties:
- Server breach reveals only the OPRF key and envelope, not the password. Offline cracking requires the OPRF to be evaluated, which itself requires a server-side secret.
- Phishing-resistant if the channel uses a fresh server key per session and the client checks it.
- Compatible with hardware-stored OPRF keys on the server side.
Adoption is slow but growing: WhatsApp uses an OPRF for backup password verification; Cloudflare experiments with OPAQUE for user portals.
OPRF: the underlying primitive
An Oblivious Pseudorandom Function lets a client compute F(k, x) where the server holds k and the client holds x, with neither learning the other's input. Implementations use blinded elliptic-curve operations (e.g., 2HashDH on prime-order groups).
Beyond OPAQUE: HIBP's k-anonymity password check uses an OPRF variant; Privacy Pass token issuance uses one; private set intersection protocols use them. The primitive is becoming common as a building block.
What replaces passwords
Passkeys (synced WebAuthn credentials) are the operational answer for most consumer sites. Three implications:
- Account recovery becomes the new authentication problem. If your passkey is gone (lost device, no sync), how do you recover? The sane modern answer: another passkey on another device, registered ahead of time.
- Cross-device flows: hybrid transport (caBLE) lets you sign in on a desktop using a phone's passkey via BLE proximity. The UX is finally usable in 2025.
- Legacy long tail: enterprises with 20-year-old systems will run passwords for another decade at minimum. Argon2id remains the right server-side hash for that long tail.