Rustelo/info/argon2_migration.md
Jesús Pérex 2f0f807331 feat: add dark mode functionality and improve navigation system
- 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>
2025-07-11 20:53:20 +01:00

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 number
  • m=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

  1. Memory-Hard Function: Resistant to specialized hardware attacks
  2. Configurable Parameters: Can adjust memory, time, and parallelism
  3. Side-Channel Resistance: Better protection against timing attacks
  4. Future-Proof: Designed to remain secure as hardware advances
  5. 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:

  1. Change their password
  2. Reset their password
  3. Update their profile (if password confirmation is required)

📚 Resources

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.