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.
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:
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
[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
[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);
}
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