.NET  

How to Implement Secure Password Hashing Using Bcrypt in .NET

Introduction

When building secure applications in ASP.NET Core or any .NET-based system, handling user passwords correctly is one of the most critical responsibilities. Storing plain-text passwords is a serious security risk and can lead to data breaches if your database is compromised.

To protect user credentials, developers use password hashing techniques. One of the most trusted and widely used approaches is bcrypt password hashing in .NET.

Bcrypt is designed specifically for securely hashing passwords, making it resistant to brute-force attacks and modern hardware-based cracking attempts.

In this guide, we will walk through how to implement secure password hashing using bcrypt in .NET step by step, along with practical examples and best practices used in real-world applications.

What is Password Hashing?

Password hashing is the process of converting a plain-text password into a fixed-length string using a cryptographic algorithm.

Key characteristics:

  • One-way transformation (cannot be reversed)

  • Same input produces same hash (with same salt)

  • Used to verify passwords without storing them

Example

Password:

mypassword123

Hashed Output:

$2a$11$e0NRo4l7... (truncated)

Instead of storing the original password, only the hash is stored in the database.

Why Use Bcrypt for Password Hashing in .NET?

Bcrypt is specifically designed for password security.

Key Benefits

  • Built-in salting mechanism

  • Adjustable work factor (cost)

  • Resistant to brute-force attacks

  • Widely adopted in production systems

Unlike simple hashing algorithms like SHA256, bcrypt is intentionally slow, which makes it more secure.

Step 1: Install Bcrypt Package in .NET

To use bcrypt in ASP.NET Core, install the library:

dotnet add package BCrypt.Net-Next

Explanation

  • BCrypt.Net-Next is a popular library for bcrypt hashing in .NET

  • It provides simple APIs for hashing and verifying passwords

Step 2: Hash a Password Before Storing

using BCrypt.Net;

string password = "MySecurePassword123";
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(password);

Console.WriteLine(hashedPassword);

Explanation

  • HashPassword() automatically generates a salt

  • The result includes salt + hash combined

  • This hash is what you store in your database

Step 3: Store Hashed Password in Database

Example User Model:

public class User
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string PasswordHash { get; set; }
}

Explanation

  • Never store plain passwords

  • Only store PasswordHash

  • Even if database is leaked, original password is protected

Step 4: Verify Password During Login

string enteredPassword = "MySecurePassword123";

bool isValid = BCrypt.Net.BCrypt.Verify(enteredPassword, hashedPassword);

if (isValid)
{
    Console.WriteLine("Login successful");
}
else
{
    Console.WriteLine("Invalid credentials");
}

Explanation

  • Verify() compares entered password with stored hash

  • Internally extracts salt and re-hashes input

  • Returns true if passwords match

Step 5: Use Work Factor (Cost) for Security

string hashed = BCrypt.Net.BCrypt.HashPassword(password, workFactor: 12);

Explanation

  • Work factor controls hashing complexity

  • Higher value = more secure but slower

  • Recommended range: 10–14

This helps future-proof your application against faster hardware attacks.

Step 6: Implement in ASP.NET Core Service

public class PasswordService
{
    public string HashPassword(string password)
    {
        return BCrypt.Net.BCrypt.HashPassword(password);
    }

    public bool VerifyPassword(string password, string hash)
    {
        return BCrypt.Net.BCrypt.Verify(password, hash);
    }
}

Explanation

  • Encapsulates hashing logic

  • Keeps controllers clean

  • Easy to reuse across application

Step 7: Use in Controller (Registration & Login)

Registration

[HttpPost("register")]
public IActionResult Register(User user)
{
    user.PasswordHash = _passwordService.HashPassword(user.PasswordHash);
    // Save user to database
    return Ok();
}

Login

[HttpPost("login")]
public IActionResult Login(string email, string password)
{
    var user = GetUserFromDatabase(email);

    if (user == null)
        return Unauthorized();

    bool isValid = _passwordService.VerifyPassword(password, user.PasswordHash);

    if (!isValid)
        return Unauthorized();

    return Ok("Login successful");
}

Explanation

  • Hash password during registration

  • Verify password during login

  • Never compare plain-text passwords

Best Practices for Secure Password Handling

  • Always hash passwords before storing

  • Use strong work factor

  • Never log passwords

  • Use HTTPS for data transmission

  • Combine with authentication systems (JWT, Identity)

Common Mistakes to Avoid

  • Storing plain-text passwords

  • Using fast hashing algorithms like MD5 or SHA1

  • Reusing salts manually

  • Ignoring password security in APIs

Real-World Example

In a real application:

  • User registers → password is hashed using bcrypt

  • Stored in database securely

  • During login → password is verified using stored hash

Even if the database is compromised, attackers cannot easily recover original passwords.

Advantages of Using Bcrypt in .NET

  • Strong security

  • Built-in salt handling

  • Adjustable complexity

  • Easy integration with ASP.NET Core

Limitations to Consider

  • Slightly slower due to security design

  • Requires proper configuration of work factor

When Should You Use Bcrypt?

Use bcrypt when:

  • Building authentication systems

  • Handling user credentials

  • Developing secure APIs or web applications

Summary

Implementing secure password hashing using bcrypt in .NET is essential for protecting user data and building secure applications. By hashing passwords before storing them, using built-in salting, and verifying credentials properly during login, developers can significantly reduce security risks. Bcrypt provides a strong, industry-standard approach that balances security and performance, making it a reliable choice for modern ASP.NET Core applications.