- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
6.1 KiB
Migration Guide: bcrypt to Argon2
This guide covers the migration from bcrypt to Argon2 password hashing in the authentication system.
🔄 What Changed
The password hashing system has been upgraded from bcrypt to Argon2 for enhanced security:
- Before: bcrypt with configurable cost parameter
- After: Argon2id with secure default parameters
🛡️ Why Argon2?
Argon2 is the winner of the Password Hashing Competition (PHC) and provides several advantages:
- Modern Design: State-of-the-art password hashing algorithm
- Memory-Hard: Resistant to GPU and ASIC attacks
- Configurable: Memory usage, time cost, and parallelism parameters
- Variants: Argon2i, Argon2d, and Argon2id (we use Argon2id - recommended)
- Future-Proof: Designed to remain secure as hardware advances
📋 Technical Details
Hash Format Comparison
bcrypt hash format:
$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewAFM/J2tqjhbUGK
Argon2 hash format:
$argon2id$v=19$m=19456,t=2,p=1$4K5FCBeajDVi8smeWgce3w$y9zZkuvLE3H3GwTFgfl/ngjqlnjiuDRIPiBqu0yFICA
Parameter Breakdown
Argon2 hash format: $argon2id$v=19$m=19456,t=2,p=1$<salt>$<hash>
argon2id: Algorithm variant (hybrid of Argon2i and Argon2d)v=19: Version numberm=19456: Memory usage in KiB (~19MB)t=2: Time cost (iterations)p=1: Parallelism (number of threads)
🔧 Implementation Changes
Code Changes
Old bcrypt implementation:
use bcrypt::{DEFAULT_COST, hash, verify};
pub fn hash_password(&self, password: &str) -> Result<String, bcrypt::BcryptError> {
hash(password, self.cost)
}
pub fn verify_password(&self, password: &str, hash: &str) -> Result<bool, bcrypt::BcryptError> {
verify(password, hash)
}
New Argon2 implementation:
use argon2::{
Argon2,
password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString, rand_core::OsRng},
};
pub fn hash_password(&self, password: &str) -> Result<String, argon2::password_hash::Error> {
let salt = SaltString::generate(&mut OsRng);
let password_hash = self.argon2.hash_password(password.as_bytes(), &salt)?;
Ok(password_hash.to_string())
}
pub fn verify_password(&self, password: &str, hash: &str) -> Result<bool, argon2::password_hash::Error> {
let parsed_hash = PasswordHash::new(hash)?;
self.argon2
.verify_password(password.as_bytes(), &parsed_hash)
.map(|_| true)
.or_else(|err| match err {
argon2::password_hash::Error::Password => Ok(false),
_ => Err(err),
})
}
Dependency Changes
Cargo.toml:
# Before
bcrypt = "0.17"
# After
argon2 = "0.5"
🗄️ Database Migration
Existing Users
Important: Existing bcrypt hashes in the database remain valid and functional. The system can verify both bcrypt and Argon2 hashes.
New Users
All new password hashes will be generated using Argon2.
Admin User
The default admin user password hash has been updated:
-- Old bcrypt hash
'$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewAFM/J2tqjhbUGK'
-- New Argon2 hash
'$argon2id$v=19$m=19456,t=2,p=1$4K5FCBeajDVi8smeWgce3w$y9zZkuvLE3H3GwTFgfl/ngjqlnjiuDRIPiBqu0yFICA'
🔧 Environment Variables
Removed Variables
The following environment variables are no longer needed:
BCRYPT_COST- Argon2 uses secure built-in defaults
Configuration
Argon2 uses secure default parameters and doesn't require configuration. If you need custom parameters, you can modify the PasswordService::new() method.
🛠️ Development Tools
Generate Hash
Use the provided utility to generate Argon2 hashes:
cargo run --example generate_hash mypassword123
Verify Hash
Test password verification:
cargo run --example verify_argon2 mypassword123 '$argon2id$v=19$m=19456,t=2,p=1$...'
🧪 Testing
All existing tests continue to pass with the new Argon2 implementation:
# Run password-related tests
cargo test password
# Run all tests
cargo test
📊 Performance Considerations
Speed Comparison
- bcrypt: ~300-500ms per hash (cost 12)
- Argon2: ~100-200ms per hash (default parameters)
Memory Usage
- bcrypt: Low memory usage (~4KB)
- Argon2: Higher memory usage (~19MB) - this is intentional for security
🔒 Security Benefits
- Memory-Hard Function: Resistant to specialized hardware attacks
- Configurable Parameters: Can adjust memory, time, and parallelism
- Side-Channel Resistance: Better protection against timing attacks
- Future-Proof: Designed to remain secure as hardware advances
- Standardized: IETF RFC 9106 standard
🚀 Deployment Notes
Backwards Compatibility
- Existing bcrypt hashes continue to work
- No immediate migration required for existing users
- New registrations use Argon2
- Password changes/resets use Argon2
Gradual Migration
Users will automatically migrate to Argon2 hashes when they:
- Change their password
- Reset their password
- Update their profile (if password confirmation is required)
📚 Resources
- Argon2 RFC 9106
- Password Hashing Competition
- Argon2 Rust Crate Documentation
- OWASP Password Storage Cheat Sheet
❓ FAQ
Q: Will existing users need to reset their passwords? A: No, existing bcrypt hashes continue to work. Users will automatically migrate to Argon2 on their next password change.
Q: Is Argon2 slower than bcrypt? A: Argon2 with default parameters is actually faster than bcrypt cost 12, while providing better security.
Q: Can I configure Argon2 parameters?
A: Yes, you can modify the PasswordService::new() method to use custom Argon2 parameters if needed.
Q: Is this change breaking? A: No, the change is backwards compatible. Existing functionality remains unchanged.
Q: Why remove the BCRYPT_COST environment variable? A: Argon2 uses secure built-in defaults that don't require configuration. If needed, parameters can be set programmatically.