Password Hashing in ASP.NET Core 3.1 with BCrypt

Password Hashing in ASP.NET Core 3.1 with BCrypt

Password Hashing in ASP.NET Core 3.1 with BCrypt

In this article, we are going to demonstrate how to hash and verify passwords in ASP.NET Core 3.1 using the BCrypt.Net-Next password hashing library which is a C# implementation of the bcrypt password hashing function.

Why Password Hashing is Important

Storing passwords in plain text is one of the worst security mistakes an application can make. Password hashing provides an additional layer of security by converting passwords into irreversible, fixed-length character strings. BCrypt is particularly secure because it incorporates a salt to protect against rainbow table attacks and is computationally intensive to resist brute-force attacks.

Security Note: Never store passwords in plain text. Always use a strong, adaptive hashing algorithm like BCrypt, which is specifically designed for password hashing.

Step-by-Step Implementation

1. Install BCrypt.Net-Core

First, we need to install the BCrypt.Net-Core package via Package Manager Console:


# Install via Package Manager Console
PM> Install-Package BCrypt.Net-Core
                    

Alternatively, you can use the .NET CLI:


dotnet add package BCrypt.Net-Core
                    

2. Create Login Model

Next, we'll create a user model to handle login information:

UsersModel.cs

public class UsersModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}
                    

3. Hashing a Password

Hashing a password with BCrypt is straightforward:


string hashedPassword = BCrypt.Net.BCrypt.HashPassword("YourPassword");
                    

The library automatically handles salt generation and incorporates it into the resulting hash string.

4. Verifying a Password

To verify a password against a stored hash:


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

This method extracts the salt from the stored hash and uses it to hash the provided password, then compares the results.

Putting it All Together in Controller

Here's how to implement registration and login functionality in your ASP.NET Core controller:

Registration Action

RegistrationController.cs

[HttpPost]
[ValidateAntiForgeryToken]
public async Task Register(UsersModel usersModel)
{
    if (ModelState.IsValid)
    {
        // Hash the password before storing
        usersModel.Password = BCrypt.Net.BCrypt.HashPassword(usersModel.Password);
        _context.Add(usersModel);
        await _context.SaveChangesAsync();
        TempData["Message"] = "Register Success";
        return RedirectToAction(nameof(Index));
    }
    TempData["Message"] = "Register Failed";
    return View(usersModel);
}
                

Login Action

LoginController.cs

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Login(UsersModel usersModel)
{
    if (ModelState.IsValid)
    {
        // Retrieve user by email
        var query = _context.UsersModel.Where(s => s.Email == usersModel.Email);
        string hashedPassword = (query.Any()) ? query.FirstOrDefault().PasswordHash : null;

        if (!string.IsNullOrEmpty(hashedPassword))
        {
            // Verify the provided password against the stored hash
            if (BCrypt.Net.BCrypt.Verify(usersModel.Password, hashedPassword))
            {
                TempData["Message"] = "Login Success";
                return RedirectToAction(nameof(Index));
            }
        }

        TempData["Message"] = "Wrong login details";
        return View(usersModel);
    }
    TempData["Message"] = "Login Failed";
    return View(usersModel);
}
                
Best Practice: Always use parameterized queries or Entity Framework to prevent SQL injection when checking user credentials. Also consider implementing rate limiting to prevent brute force attacks.

Conclusion

Implementing secure password storage is crucial for any application that handles user authentication. BCrypt provides a robust solution for password hashing in ASP.NET Core applications. By following this guide, you can ensure that your users' passwords are stored securely, protecting both your users and your application from potential security breaches.

Remember that security is an ongoing process. Always keep your dependencies updated and stay informed about the latest security best practices.

Comments