Hashing vs. Encryption: A Critical Distinction
The article clarifies that these are fundamentally different operations. "Encryption is a two-way, reversible process" while "Hashing is a one-way, irreversible process." The critical security principle: if passwords can be decrypted, the system is flawed by design.
Why Fast Hashes Are Dangerous for Passwords
General-purpose cryptographic hash functions like SHA-256 are inappropriate for password storage because they're too efficient. The text illustrates the vulnerability: "SHA-256 on modern GPU: ~180 billion hashes/second" versus "Argon2 on same GPU: ~1,000 hashes/second", a 180-million-fold difference in attacker efficiency.
The Three Pillars of Secure Password Hashing
Modern password hashing relies on three foundational principles:
- Deliberate Computational Cost: Algorithms must be intentionally slow, targeting "200-500ms per hash on production hardware"
- Memory Hardness: Requiring significant RAM makes parallel GPU attacks expensive
- Cryptographic Salt: Each password needs a unique, randomly generated salt to prevent rainbow table attacks and enable individual cracking attempts
Salt requirements are explicit: "minimum 128-bit (16-byte) salt length" generated with cryptographically secure random generators, never reused, and stored alongside hashes (salts need not be secret).
Understanding Work Factors and Adaptive Hashing
All modern algorithms use configurable "work factors" allowing security to increase without algorithm changes. The example shows bcrypt cost factor evolution: "2010: cost factor of 10 = 100ms" progressing to "2025: cost factor of 14 = 1000ms."
Password Hashing Workflow
The complete process involves four registration steps: password submission, random salt generation, hash computation, and plaintext password removal from memory. For authentication, the system retrieves stored hash parameters, recomputes the hash with provided credentials, and performs "constant-time comparison" to prevent timing attacks.
Common Misconceptions
The article debunks several myths:
- Stacking hash functions (bcrypt(md5(password))) doesn't improve security
- Salts should be unique, not secret
- Excessive iterations can paradoxically create denial-of-service vulnerabilities
- SHA-256's Bitcoin use doesn't make it suitable for passwords
Argon2: The Modern Standard
Background and Development
Argon2 emerged as the "Password Hashing Competition winner in 2015" after rigorous evaluation against GPU and ASIC attack requirements. Now specified in RFC 9106, it represents "the gold standard for password hashing in 2025."
The Three Variants: Argon2d, Argon2i, and Argon2id
- Argon2d: Maximum GPU resistance but vulnerable to timing attacks
- Argon2i: Side-channel resistant but slightly less GPU-resistant
- Argon2id (RECOMMENDED): Hybrid approach balancing both protections
The recommendation is unambiguous: "OWASP and security experts universally recommend Argon2id" for general-purpose applications.
Argon2 Parameters Explained
Three configurable parameters control security:
- Memory Cost (m): RAM usage in kilobytes; typically 15-256MB
- Time Cost (t): Number of passes through memory; typically 1-5 iterations
- Parallelism (p): Concurrent threads; typically 1-4
The trade-offs are explicit: higher parameters mean better security but increased resource consumption.
How Argon2 Works: Technical Deep Dive
The algorithm progresses through four phases: initialization using Blake2b hashing of password components, memory filling with pseudorandom data creating dependencies, memory mixing through multiple iterations (with access patterns differing by variant), and finalization extracting the hash.
The critical security property: "Each access involves computing Blake2b hash and XOR operations" and "Pattern forces attacker to maintain full memory to compute hash."
Argon2 Hash Format
Hashes encode all parameters in a self-describing format: $argon2id$v=19$m=65536,t=3,p=4$[salt]$[hash], allowing systems to change parameters over time while maintaining backward compatibility.
OWASP Recommended Argon2 Configurations (2025)
Three tiers address different requirements:
- Minimum: 19 MiB memory, 2 iterations = 100-150ms
- Recommended: 46 MiB memory, 1 iteration = 150-200ms
- High-Security: 128 MiB memory, 3 iterations = 300-500ms
The principle is straightforward: "These configurations provide equivalent security through different trade-offs between memory and CPU usage."
Advantages of Argon2
Seven key strengths include state-of-the-art security specifically designed for modern attacks, memory hardness making GPU/ASIC attacks economically infeasible, configurable parameters allowing precise tuning, side-channel resistance through the Argon2id variant, future-proofing through parameter increases, RFC 9106 standardization, and "wide platform support: available across all major languages and frameworks."
Limitations of Argon2
Five limitations exist: being relatively newer than bcrypt, higher resource requirements, more complex parameter selection, legacy system incompatibility, and potential mobile device constraints due to memory needs.
When to Use Argon2
Use Argon2id for new systems with modern infrastructure and adequate server resources (32MB+ per operation). Consider alternatives for extremely constrained environments, legacy systems without library support, or mandatory FIPS-140 compliance.
Bcrypt: The Proven Workhorse
Background and Development
Designed in 1999 by Niels Provos and David Mazieres, bcrypt remains viable after 25 years. Its innovation: adapting Blowfish's "computationally expensive key setup phase" into an adaptive password function.
How Bcrypt Works
Bcrypt's security derives from its key setup process: generating a 128-bit salt, performing "2^cost iterations" of key expansion (cost factor of 10 = 1,024 iterations; cost factor of 14 = 16,384 iterations), then encrypting fixed text 64 times. Each cost increment doubles required work.
Bcrypt Hash Format
The encoded format reveals parameters: $2b$12$[salt22chars]$[hash31chars] where the prefix indicates variant (use $2b$), the number indicates cost factor, and remaining components encode salt and hash output.
The 72-Byte Password Limit
A well-known constraint: bcrypt "only processes the first 72 bytes of input." This creates security issues when passwords exceed this threshold, identical hashes result from passwords differing after byte 72. The solution is pre-hashing longer passwords with SHA-384 before bcrypt processing.
OWASP Recommended Bcrypt Configuration (2025)
Current guidance recommends cost factor 12 (250ms typical) or factor 14 (1000ms) for higher security. Cost factors should increase annually as hardware improves, what takes 100ms today may take 50ms in two years.
Advantages of Bcrypt
Seven strengths include proven security after 25 years, simplicity (single work factor parameter), universal platform support, predictable performance, minimal memory needs (4KB), extensive documentation, and native PHP support.
Limitations of Bcrypt
Limitations include minimal memory usage (vulnerability to GPU attacks), 72-byte input limit, inability to leverage multi-core processors, lower GPU resistance than newer algorithms, and unchangeable algorithm parameters beyond cost factor.
When to Use Bcrypt
Use bcrypt for maintaining existing systems, legacy infrastructure compatibility, memory-constrained environments (< 32MB available), or prioritizing simplicity. Modern systems should prefer Argon2id.
Scrypt: Memory-Hard Pioneer
Background and Development
Colin Percival created scrypt in 2009 for the Tarsnap backup service, introducing "sequential memory-hard algorithm" concepts later influencing Argon2. Its key innovation makes memory maintenance mandatory, preventing time-memory trade-offs attackers might exploit.
How Scrypt Works
Scrypt uses a two-stage process: initial PBKDF2-HMAC-SHA-256 key derivation (one iteration), then ROMix memory-hard mixing. The mixing phase critically requires "random access to the entire memory block" since access patterns are unpredictable, forcing attackers to maintain complete memory arrays.
Scrypt Parameters Explained
Three parameters control security: N (power-of-2 cost parameter determining memory and iterations), r (typically 8 block size parameter), and p (usually 1 parallelization factor). Memory usage formula: N x 128 bytes total.
OWASP Recommended Scrypt Configuration (2025)
Three tiers address different needs:
- Minimum: N=2^15 (32MB) = 100ms
- Recommended: N=2^17 (128MB) = 200ms
- High-Security: N=2^18 (256MB) = 400ms
Advantages of Scrypt
Seven strengths: strong memory hardness, GPU attack resistance, ASIC resistance, cryptocurrency validation through Litecoin use, three-parameter flexibility, 15+ years of cryptanalysis, and proven design effectiveness.
Limitations of Scrypt
Limitations include being superseded by Argon2, side-channel vulnerabilities through data-dependent memory access, high resource usage, complex parameter selection, existing ASIC miners (though expensive), and lack of FIPS-140 validation.
Scrypt vs Argon2: Key Differences
A comparison table shows Argon2 offering stronger memory hardness, superior side-channel resistance, more intuitive parameters, and equal cryptanalysis depth despite being 5 years newer. Scrypt remains viable when Argon2 is unavailable.
When to Use Scrypt
Use scrypt when Argon2 isn't available, migrating from PBKDF2 gradually, handling cryptocurrency applications, or needing stronger security than bcrypt with memory constraints. Choose Argon2id for new systems.
PBKDF2: The Legacy Standard
Background and Development
PBKDF2 was designed by RSA Laboratories in 2000 per RFC 2898 as part of PKCS standards. It serves dual purposes: deriving encryption keys and hashing passwords through repeated application of pseudorandom functions, intentionally slowing computation.
How PBKDF2 Works
The algorithm iteratively applies HMAC (typically HMAC-SHA256) repeatedly to password and salt: computing U1, U2 through Un as successive applications, then XORing all intermediate values. Iteration count directly controls computational cost.
PBKDF2 Parameters
Configurable elements include hash function (use HMAC-SHA-256, not deprecated SHA-1), iteration count (currently 600,000 minimum per OWASP), salt (minimum 128 bits), and output length (typically 256 bits for SHA-256).
OWASP Recommended PBKDF2 Configuration (2025)
For HMAC-SHA-256: minimum 600,000 iterations; for HMAC-SHA-512: 210,000 iterations minimum. Target hash time is 200ms. These should increase annually as hardware improves, current recommendations are based on December 2022 GPU benchmarks.
Advantages of PBKDF2
Eight strengths: FIPS-140 validation (the only algorithm among four with this), government regulatory compliance, NIST recommendation in SP 800-132, universal support, simple single-parameter configuration, minimal memory requirements, decades of cryptanalysis, and predictable performance.
Limitations of PBKDF2
Five limitations: complete absence of memory hardness (making GPU attacks efficient), GPU vulnerability enabling billions of computations per second, ASIC vulnerability, requiring constantly increasing iterations as hardware improves, and inferiority to modern alternatives like Argon2 and scrypt.
PBKDF2 Attack Economics
Cost estimates for AWS GPU farms reveal stark differences: 8-character passwords cost "$10,000 to crack" with 600,000 iterations versus "~$500 million" with Argon2, demonstrating that "PBKDF2's lack of memory hardness makes it 1,000-10,000x cheaper to attack."
When to Use PBKDF2
Use PBKDF2 only when FIPS-140 compliance is mandatory, government regulations require it, NIST-approved algorithms are specified, or legacy system constraints prevent upgrades. Modern systems should use Argon2id instead.
Head-to-Head Comparison
Security Matrix
The four algorithms differ significantly in their defensive capabilities:
| Feature | Argon2id | Bcrypt | Scrypt | PBKDF2 |
|---|---|---|---|---|
| Memory Hardness | ★★★★★ | ★☆☆☆☆ | ★★★★☆ | ★☆☆☆☆ |
| GPU Resistance | ★★★★★ | ★★☆☆☆ | ★★★★☆ | ★☆☆☆☆ |
| ASIC Resistance | ★★★★★ | ★★☆☆☆ | ★★★★☆ | ★☆☆☆☆ |
| Side-Channel Resistance | ★★★★★ | ★★★☆☆ | ★★☆☆☆ | ★★★☆☆ |
| Configuration Flexibility | ★★★★★ | ★★☆☆☆ | ★★★★☆ | ★★☆☆☆ |
| Platform Support | ★★★★☆ | ★★★★★ | ★★★★☆ | ★★★★★ |
| FIPS Validated | ✗ | ✗ | ✗ | ✓ |
Performance Benchmarks
Hash times on Intel Xeon E5-2680 @ 2.7GHz:
| Algorithm | Configuration | Time | Memory |
|---|---|---|---|
| Argon2id | m=64MB, t=3, p=1 | 250ms | 64 MB |
| Bcrypt | cost=12 | 250ms | 4 KB |
| Scrypt | N=2^17, r=8, p=1 | 350ms | 128 MB |
| PBKDF2 | 600k iterations | 200ms | <1 MB |
Attack Cost Analysis
Estimated AWS GPU instance costs to crack an 8-character complex password:
| Algorithm | Configuration | Cracking Time | Cost |
|---|---|---|---|
| PBKDF2 | 600k iterations | 3 days | $5,000 |
| Bcrypt | cost=12 | 30 days | $40,000 |
| Scrypt | N=2^17 | 200 days | $300,000 |
| Argon2id | m=128MB, t=3 | 500 days | $750,000 |
Memory-hard algorithms create exponentially higher economic barriers for attackers compared to iteration-only approaches.
GPU Attack Performance
Real-world GPU advantage (NVIDIA RTX 4090) compared to CPU:
| Algorithm | Hashes/Second (GPU) | CPU Speedup |
|---|---|---|
| MD5 | 186 billion | 620,000x |
| PBKDF2 (600k) | 850,000 | 4,700x |
| Bcrypt (cost=12) | 95,000 | 396x |
| Scrypt (N=2^17) | 2,800 | 8x |
| Argon2id (128MB) | 380 | 1.5x |
Memory-hard functions reduce GPU advantage dramatically, Argon2 with adequate memory is only marginally faster on accelerated hardware versus CPUs.
Selection Decision Framework
The guide provides a decision tree for algorithm selection:
- FIPS-140 compliance required? → Use PBKDF2 with HMAC-SHA-256, 600k+ iterations
- Maintaining existing system? → Keep current algorithm, increase parameters; plan gradual migration
- Memory constraints exist? → Use bcrypt with cost factor 12+
- Building new system? → Use Argon2id (m=64MB+, t=3, p=1)
Default recommendation: "Argon2id" for new implementations offers superior security against modern attack methods.
Platform Support Overview
All algorithms have mature library support across languages. Argon2 and PBKDF2 are available natively or through established packages in Python, Node.js, PHP, Java, C#, Go, and Rust. Bcrypt enjoys particularly widespread native support, while scrypt requires library installation in most languages.
Use Case Recommendations
- New web applications: Argon2id with standard parameters
- Existing bcrypt deployments: Increase cost factor gradually; plan future Argon2 migration
- Government/financial systems: PBKDF2 for compliance
- Mobile backends: Argon2id with reduced memory (m=32MB)
- IoT/embedded: Bcrypt due to minimal resources needed
- Cryptocurrency wallets: Scrypt or Argon2d for offline use
Implementation Best Practices
The article emphasizes that secure password hashing requires adherence to fundamental principles before implementing any algorithm. Developers should "never roll your own crypto" but instead use "established libraries," and must employ each library's built-in verification functions rather than manually comparing hash values. Every password requires a "unique, cryptographically random salt" that should be stored alongside the hash, salts are intentionally not secret, merely unique.
Core Implementation Requirements
The guide stresses that "password comparison must use constant-time comparison to prevent timing attacks." Most modern frameworks provide this functionality natively (such as password_verify() in PHP or bcrypt.compare() in Node.js).
When implementing across platforms, the article provides production-ready examples in Python demonstrating proper error handling and edge case management. For instance, because Bcrypt truncates input at 72 bytes, implementations handling longer passwords should "pre-hash with SHA-384 or SHA-256" before applying Bcrypt to eliminate this vulnerability.
Configuration Tuning
The document recommends measuring hash times on actual production hardware rather than relying on theoretical calculations. For Argon2, administrators should "benchmark current authentication time on production hardware" and ensure configurations achieve the "target 200-500ms hash time for interactive authentication."
Migration Strategies
Lazy Upgrade Pattern
The OWASP-recommended approach involves upgrading password hashes during successful user authentication:
"During user login, check if hash needs upgrade. If the current cost factor is less than target, rehash with higher cost during successful login."
This strategy allows "gradual work factor increases without forcing password resets."
Dual-Hash Approach for Compliance
For organizations with regulatory constraints, the article describes a "dual-hash approach" storing both legacy (PBKDF2 for compliance) and modern (Argon2 for security) hashes simultaneously. During verification, the system prioritizes the stronger algorithm while maintaining backward compatibility.
Migration Priority Framework
The article provides a migration matrix categorizing urgency:
- Critical priority: Plaintext, MD5, SHA-1 (immediate action)
- High priority: SHA-256, weak PBKDF2 (within 90 days)
- Medium priority: Bcrypt with low cost factors (within 6 months)
- Low priority: Current-generation algorithms (planned upgrades)
Performance Considerations
Real-world benchmarking data demonstrates that "Argon2 provides best memory hardness for given hash time," while "Bcrypt is most predictable and consistent." For concurrent load handling, the article notes that "standard servers handling 16 requests per second with Argon2id can handle 5.7x peak load with comfortable margin."
Memory-hard algorithms require infrastructure planning: "Argon2/scrypt require adequate RAM capacity. Plan for peak load plus safety margin."
Frequently Asked Questions & Conclusion
The document includes comprehensive FAQs addressing implementation concerns. It emphasizes that all recommended modern algorithms remain secure when "properly configured with adequate work factors" and that "password hashing strategy can be the difference between passwords that are effectively impossible to crack and those that fall within hours to modern attack methods."
The overarching recommendation states: "Use Argon2id when building new authentication systems. Choose between bcrypt alternatives when maintaining existing systems. Reserve PBKDF2 exclusively for FIPS-140 compliance scenarios."