TL;DR
Yes! While bcrypt and scrypt are still good, Argon2 and PBKDF2 (with appropriate tuning) offer better resistance against modern attacks like GPU cracking. This guide explains why and how to switch.
1. Why Move Beyond Bcrypt & Scrypt?
Bcrypt and scrypt were groundbreaking but have weaknesses discovered over time, particularly with the rise of powerful hardware (GPUs). They are memory-hard, meaning they require a lot of RAM to crack quickly, but GPUs are getting more and more memory. Newer algorithms aim to be even *more* resistant.
2. Introducing Argon2
Argon2 is currently the recommended password hashing algorithm by many cyber security professionals. It’s designed to resist both GPU cracking and side-channel attacks. There are three main variants:
- Argon2d: Best for resistance against time-memory trade-offs (good if you have lots of memory).
- Argon2i: Best for resistance against side-channel attacks (good if you’re worried about attackers trying to read data from your server while hashing).
- Argon2id: A hybrid approach, offering a good balance between the two. This is often the best general choice.
Most libraries default to Argon2id.
3. Introducing PBKDF2
Password-Based Key Derivation Function 2 (PBKDF2) isn’t new, but it’s still very strong *if* configured correctly. The key is using a high iteration count and a good salt.
4. How to Switch: Practical Steps
- Choose a Library: Select a library for your programming language that supports Argon2 or PBKDF2. Examples:
- Python: argon2-cffi, hashlib (for PBKDF2)
- PHP: PHPass (supports bcrypt, scrypt and PBKDF2), Argon2 PHP
- Node.js: bcryptjs (also supports Argon2)
- Generate Salts: Always use a unique, randomly generated salt for each password. A good length is 16-32 bytes.
# Python example using os.urandom import os salt = os.urandom(16) - Hash the Password: Use your chosen library to hash the password with the salt.
# Python Argon2 example (argon2-cffi) from argon2 import PasswordHasher ph = PasswordHasher() hash = ph.hash("your_password", salt=salt)# Python PBKDF2 example import hashlib salt = os.urandom(16) key = hashlib.pbkdf2_hmac('sha256', 'your_password'.encode(), salt, 100000) # High iteration count! - Store the Hash & Salt: Store both the generated hash and the salt in your database. *Never* store passwords in plain text.
- Verification: When a user logs in, retrieve the stored hash and salt for that user. Re-hash the entered password using the same salt and compare the resulting hash with the stored hash.
# Python Argon2 verification example ph = PasswordHasher() try: ph.verify(hash, "user_entered_password") except Exception as e: print("Password incorrect!") - Iteration Count/Memory Settings: For PBKDF2, increase the iteration count until hashing takes around 0.5-1 second on your server. For Argon2, adjust the time cost (t), memory cost (m), and parallelism (p) parameters to achieve a similar hashing time.
5. Important Considerations
- Regular Updates: Keep your libraries updated to benefit from security patches.
- Hardware Changes: Re-evaluate your iteration count/memory settings periodically as hardware improves.
- Database Security: Protect your database from unauthorized access. A strong password hashing algorithm is useless if an attacker can steal the hashes directly.