Published:

.NET 6.0 - Hash and Verify Passwords with BCrypt

Tutorial built with .NET 6.0

Other versions available:

This is a quick example of how to hash and verify passwords in .NET 6.0 using the BCrypt.Net-Next password hashing library which is a C# implementation of the bcrypt password hashing function.

For more info on the BCrypt.Net-Next password hashing C# library see https://www.nuget.org/packages/BCrypt.Net-Next.

For more info on the underlying bcrypt password hashing function, see https://en.wikipedia.org/wiki/bcrypt.


Installing BCrypt.Net-Next via NuGet

.NET CLI: dotnet add package BCrypt.Net-Next

Visual Studio Package Manager Console: Install-Package BCrypt.Net-Next


Hashing a password in .NET 6.0

The following line of code hashes the password "Pa$$w0rd" using bcrypt and stores the result in the passwordHash string variable.

string passwordHash = BCrypt.Net.BCrypt.HashPassword("Pa$$w0rd");


Verify a password against a hash in .NET 6.0

The following line of code verifies the password "Pa$$w0rd" using bcrypt against the hash stored in the passwordHash variable.

bool verified = BCrypt.Net.BCrypt.Verify("Pa$$w0rd", passwordHash);


Example usage in a .NET User Service

Below is an example .NET 6.0 user service with a Register() method that saves a user account with a hashed password and an Authenticate() method that verifies a provided password against the PasswordHash of a saved user account. The password is hashed on line 70 and verified on line 41.

The service is from a .NET API tutorial I posted recently, for more info or to download and test the API locally see .NET 6.0 - User Registration and Login Tutorial with Example API.

namespace WebApi.Services;

using AutoMapper;
using BCrypt.Net;
using WebApi.Authorization;
using WebApi.Entities;
using WebApi.Helpers;
using WebApi.Models.Users;

public interface IUserService
{
    AuthenticateResponse Authenticate(AuthenticateRequest model);
    IEnumerable<User> GetAll();
    User GetById(int id);
    void Register(RegisterRequest model);
    void Update(int id, UpdateRequest model);
    void Delete(int id);
}

public class UserService : IUserService
{
    private DataContext _context;
    private IJwtUtils _jwtUtils;
    private readonly IMapper _mapper;

    public UserService(
        DataContext context,
        IJwtUtils jwtUtils,
        IMapper mapper)
    {
        _context = context;
        _jwtUtils = jwtUtils;
        _mapper = mapper;
    }

    public AuthenticateResponse Authenticate(AuthenticateRequest model)
    {
        var user = _context.Users.SingleOrDefault(x => x.Username == model.Username);

        // validate
        if (user == null || !BCrypt.Verify(model.Password, user.PasswordHash))
            throw new AppException("Username or password is incorrect");

        // authentication successful
        var response = _mapper.Map<AuthenticateResponse>(user);
        response.Token = _jwtUtils.GenerateToken(user);
        return response;
    }

    public IEnumerable<User> GetAll()
    {
        return _context.Users;
    }

    public User GetById(int id)
    {
        return getUser(id);
    }

    public void Register(RegisterRequest model)
    {
        // validate
        if (_context.Users.Any(x => x.Username == model.Username))
            throw new AppException("Username '" + model.Username + "' is already taken");

        // map model to new user object
        var user = _mapper.Map<User>(model);

        // hash password
        user.PasswordHash = BCrypt.HashPassword(model.Password);

        // save user
        _context.Users.Add(user);
        _context.SaveChanges();
    }

    public void Update(int id, UpdateRequest model)
    {
        var user = getUser(id);

        // validate
        if (model.Username != user.Username && _context.Users.Any(x => x.Username == model.Username))
            throw new AppException("Username '" + model.Username + "' is already taken");

        // hash password if it was entered
        if (!string.IsNullOrEmpty(model.Password))
            user.PasswordHash = BCrypt.HashPassword(model.Password);

        // copy model to user and save
        _mapper.Map(model, user);
        _context.Users.Update(user);
        _context.SaveChanges();
    }

    public void Delete(int id)
    {
        var user = getUser(id);
        _context.Users.Remove(user);
        _context.SaveChanges();
    }

    // helper methods

    private User getUser(int id)
    {
        var user = _context.Users.Find(id);
        if (user == null) throw new KeyNotFoundException("User not found");
        return user;
    }
}

 


Subscribe or Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter, Facebook or GitHub to be notified when I post new content.

Other than coding...

I'm currently attempting to travel around Australia by motorcycle with my wife Tina on a pair of Royal Enfield Himalayans. You can follow our adventures on YouTube, Instagram and Facebook.


Need Some .NET Help?

Search fiverr to find help quickly from experienced .NET developers.



Supported by