Why password hashing matters
Storing passwords safely is one of the simplest yet most frequent security failures. Plain text or simple cryptographic hashes like a single SHA-256 call let attackers who gain access to the database test millions of guesses per second with GPUs or specialized hardware. Password hashing functions purposely slow down verification and use memory to make brute-force and parallelized attacks expensive. Choosing the right function and tuning its parameters can make a practical difference in whether an attacker can recover many passwords from a breach.
What is Argon2?
Argon2 is a modern password-hashing and key-derivation function that won the Password Hashing Competition in 2015 and was designed specifically to resist GPU and ASIC crackers by being memory-hard and parallelizable in a controlled way. It comes in three variants: Argon2d (data-dependent memory access), Argon2i (data-independent memory access), and Argon2id (a hybrid that starts with Argon2i-like passes and then uses Argon2d). For most password-storage uses, Argon2id is recommended because it strikes a balance between side-channel resistance and resistance to parallel brute force. Argon2 exposes tuneable parameters for time (iterations), memory (amount of RAM used), and parallelism (threads), letting you adapt cost to your server capacity and threat model.
Common alternatives: bcrypt, scrypt, PBKDF2
bcrypt, scrypt, and PBKDF2 are widely used, well-understood alternatives that remain in active use because of broad library support and regulatory acceptance. PBKDF2 is part of many standards and uses HMAC (typically HMAC-SHA256) iterated many times; it is CPU-bound and easy to implement but not memory-hard, so it is less effective against modern parallel hardware. bcrypt is older, based on the Blowfish cipher, and adds a work factor to slow hashing; it resists some attack patterns but has limited memory hardness and a maximum password length quirk. scrypt introduced memory-hardness before Argon2, combining CPU cost with significant memory requirements to slow down GPUs, and is still a solid choice when Argon2 isn’t available.
How Argon2 compares: security, speed, and cost
At a high level, Argon2 improves on earlier designs by providing configurable memory hardness and parallelism together with variants that consider side-channel threats. Against an attacker with many parallel GPUs or ASICs, a memory-hard function like Argon2 or scrypt forces each parallel instance to allocate and use a lot of RAM, which quickly becomes the limiting factor. PBKDF2 and bcrypt are cheaper for attackers on highly parallel hardware because they primarily consume CPU, not RAM. In raw performance, bcrypt and PBKDF2 are typically faster for low-cost settings, but that speed is a downside for password storage because it reduces the computational work required to try guesses.
Key comparison points
- Memory hardness: Argon2 and scrypt are memory-hard; bcrypt and PBKDF2 are not (bcrypt has limited memory usage).
- Parallelism: Argon2 supports parallel threads with controlled internal design; scrypt has tunable parallelism; PBKDF2 is simple to parallelize across passwords rather than inside a single hash.
- Side-channel resistance: Argon2i and Argon2id are designed with side-channel considerations; Argon2d is faster but could leak in some scenarios.
- Library support and standards: PBKDF2 and bcrypt have very broad, long-standing support; Argon2 support is widespread today but not as universal in legacy systems.
Choosing parameters and practical advice
There’s no single “perfect” parameter set , choices depend on your hardware, expected traffic, and acceptable verification latency. Start by deciding an acceptable authentication latency (e.g., 100–500 ms per login check for interactive logins is a common target) and then benchmark different memory/time settings on representative servers. Aim to maximize memory before increasing iterations because memory is more expensive for attackers than extra CPU cycles. For Argon2id, a practical starting point for many services might be tens or hundreds of megabytes of memory and a small time cost (1–3 iterations), but high-security environments may opt for more memory or iterations. Always include a unique salt per password (random, 16 bytes or more), and store parameters with the hash so they can be changed later.
When to use each option
If you are building a new system and have modern library support, Argon2id is the best general-purpose choice because it offers current best-practice protection against modern hardware attacks with good flexibility. Use scrypt when Argon2 implementations are unavailable but you still want memory hardness. Choose bcrypt when you need maximum compatibility with older ecosystems; it’s still safe if you set a sufficiently high cost, though it’s less optimal than Argon2. Use PBKDF2 where regulatory or platform constraints require a standardized KDF , for example, some FIPS environments rely on PBKDF2 , but be mindful that it provides weaker protection against parallel attackers compared with memory-hard functions.
Implementation and library support
Most major languages now include libraries or bindings for Argon2: there are native implementations in C and bindings for Python, Node.js, Java, Go, Rust and others. Many cryptography libraries (for example, libsodium or libsodium-based wrappers) expose Argon2id-style primitives with safe defaults. When using a library, prefer one that returns a PHC-style encoded string (which includes the algorithm name and parameters) so you can change parameters later without invalidating stored hashes. Guard against common mistakes: never roll your own memory-hard function, always use per-password salts, verify encoded parameter strings at verification time, and consider adding an application-level “pepper” (a server-side secret) for very high-value accounts.
Practical checklist before deployment
- Pick Argon2id for new projects unless constrained; fallback to scrypt or bcrypt where necessary.
- Benchmark on real hardware to choose memory/time/parallelism that meet your latency goals.
- Use unique, random salts and store them with each hash; use PHC-style encoding if possible.
- Plan for parameter upgrades: include versioning and a migration strategy for re-hashing on successful logins.
- Protect the database and application secrets; even the best hash slows attackers but doesn’t stop breaches entirely.
Summary
Argon2 (especially Argon2id) is the modern recommended password-hashing function because it combines memory hardness, configurable parallelism, and options that reduce side-channel risk. scrypt is a solid memory-hard alternative when Argon2 isn’t available; bcrypt and PBKDF2 remain widely used for compatibility but are less effective against highly parallel hardware attacks. The most important step is to use a purpose-built password hash (not a plain hash), choose parameters by benchmarking on your hardware, and store salts and parameter metadata so you can upgrade in the future.
FAQs
Should I switch existing bcrypt or PBKDF2 hashes to Argon2?
You don’t have to rehash every password at once. A common approach is to rehash passwords with Argon2 upon successful user login: verify the existing hash, then compute and store an Argon2 hash for that password. This lets you migrate gradually without forcing mass resets.
What Argon2 variant should I use?
Argon2id is recommended for most password storage use cases because it provides balanced protection against both side channels and brute-force parallelism. Use Argon2i only if you have a strong reason to avoid data-dependent memory access patterns, and Argon2d only in environments where side-channel leakage is not a concern and maximum resistance to GPU cracking is desired.
How do I pick memory and time settings?
Benchmark on representative hardware and choose settings that produce an acceptable authentication latency (commonly 100–500 ms). Prefer increasing memory before raising iterations because memory costs are more damaging to attackers who run many concurrent guesses. Record chosen parameters with each hash so you can adjust them later.
Can Argon2 be used as a general key derivation function?
Yes,Argon2 can derive keys for encryption or other uses, but ensure you use appropriate domain separation and parameter choices for key material. For standards-driven use cases, check whether a specific KDF (like HKDF or PBKDF2) is required by your protocol or compliance rules.
Is hardware acceleration or special hardware a concern?
Memory-hard functions are designed to reduce the advantage of GPUs and ASICs, but hardware evolves. Keep parameters under review, follow best-practice updates from the cryptography community, and design your system so parameter upgrades are possible without breaking existing accounts.