DEV Community

ZèD
ZèD

Posted on • Edited on

BCrypt vs Argon2: Password Hashing in .NET – A Practical Deep Dive

BCrypt vs Argon2 Password Hashing in .NET: A Practical Deep Dive

Password storage is one place where shortcuts become incidents. Fast hashes are good for integrity checks, but bad for password protection.

This guide compares BCrypt and Argon2 in .NET with practical trade-offs and usage patterns.

Why It Matters

  • Password hashing must be intentionally expensive.
  • Attackers use GPU/ASIC parallelism for brute-force attacks.
  • Algorithm choice impacts long-term security posture.
  • Good defaults reduce human error in auth systems.

Core Concepts

1. Why Fast Hashes Are Not Enough

Algorithms like SHA-256 are designed for speed. That is the opposite of what password hashing needs.

2. BCrypt Basics

BCrypt is battle-tested and simple to configure.

  • CPU-bound design
  • Single tuning parameter (work factor)
  • Low fixed memory cost
using BCrypt.Net;

public static class BcryptPasswordHasher
{
    private const int WorkFactor = 13;

    public static string Hash(string password)
        => BCrypt.Net.BCrypt.HashPassword(password, WorkFactor);

    public static bool Verify(string password, string hash)
        => BCrypt.Net.BCrypt.Verify(password, hash);
}
Enter fullscreen mode Exit fullscreen mode

3. Argon2 Basics

Argon2 is newer and designed to be memory-hard.

  • Recommended variant for passwords: Argon2id
  • Tunable memory/time/parallelism
  • Stronger resistance to large-scale parallel cracking
using Isopoh.Cryptography.Argon2;

public static class Argon2PasswordHasher
{
    public static string Hash(string password)
        => Argon2.Hash(password);

    public static bool Verify(string password, string hash)
        => Argon2.Verify(hash, password);
}
Enter fullscreen mode Exit fullscreen mode

4. Internal Difference Summary

  • BCrypt: mostly CPU cost
  • Argon2: CPU + memory cost

Memory hardness is the major advantage when defending against GPU-heavy attacks.

5. Parameter Tuning Reality

Benchmark on production-like hardware. Target latency often lands around 400ms-800ms per hash, depending on your SLA and login throughput.

6. Migration Strategy

When upgrading algorithm, rehash on next successful login and store new hash format.

Practical Example

Algorithm-selection helper pattern:

public interface IPasswordHasher
{
    string Hash(string password);
    bool Verify(string password, string hash);
}

public sealed class PasswordService
{
    private readonly IPasswordHasher _hasher;

    public PasswordService(IPasswordHasher hasher)
    {
        _hasher = hasher;
    }

    public string CreateHash(string password) => _hasher.Hash(password);

    public bool Validate(string password, string storedHash) => _hasher.Verify(password, storedHash);
}
Enter fullscreen mode Exit fullscreen mode

This keeps your domain logic clean and lets you switch hashing strategy without rewriting auth flows.

Common Mistakes

  • Using SHA-256 directly for passwords.
  • Keeping hash cost too low for modern hardware.
  • Migrating algorithms without rehash-on-login plan.
  • Ignoring memory pressure when tuning Argon2 under concurrency.
  • Relying on hashing alone without rate limiting and MFA.

Quick Recap

  • Use password-specific hashing, never plain fast hashes.
  • BCrypt is simple and stable for many systems.
  • Argon2id is generally stronger for modern threat models.
  • Tune cost on real hardware, not guesswork.
  • Combine with lockout, rate limit, and MFA for layered defense.

Next Steps

  1. Benchmark BCrypt vs Argon2 on your production-like environment.
  2. Define acceptable login latency and tune parameters accordingly.
  3. Implement rehash-on-login migration path.
  4. Add rate limiting and MFA to strengthen auth pipeline.

Top comments (0)