How do I check the password entered by the user? BCrypt.HashPassword(password) does not match with BD.AspNetUsers.PasswordHash.

Volk Volk 571 Reputation points
2022-07-24T21:29:11.553+00:00

Hello!

I have a website where users register. A user password is saved as a hash in BD.AspNetUsers.PasswordHash.
I have a separate proxy server that needs to verify the password entered by the user from another application.
I connect to the database of the site, try to create a hash of the password entered by the user and try find it in the database.

But this code on the server:

var hashPassword = BCrypt.Net.BCrypt.HashPassword(password);  

...creates a completely different hash of the same password for me.

How do I verify the password entered by the user on the proxy server?
Of course, I can save the real password on the site, but then why store it as a hash?

BCrypt.Net-Next.Strong Name - latest version 4.0.3. Website is on Net.core 6.

Thank you!

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
697 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,148 questions
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 26,191 Reputation points
    2022-07-26T10:16:54.553+00:00
    1 person found this answer helpful.

5 additional answers

Sort by: Most helpful
  1. AgaveJoe 26,191 Reputation points
    2022-07-25T18:15:12.37+00:00

    The problem is you are not using the BCrypt library correctly. BCrypt does not create the same hash for the same password. It creates a new hash each time.

    You must fetch the hash for the user and compare the hash to the password. Querying a table for the hash will not work. You have to know the unique ID if the records which is typically the username.

    For example.

        public static async Task Main(string[] passwordargs)  
        {  
            string passwordHash1 = BCrypt.Net.BCrypt.HashPassword("Pa$$w0rd");  
            Console.WriteLine(passwordHash1);  
      
            string passwordHash2 = BCrypt.Net.BCrypt.HashPassword("Pa$$w0rd");  
            Console.WriteLine(passwordHash2);  
      
            string passwordHash3 = BCrypt.Net.BCrypt.HashPassword("Pa$$w0rd");  
            Console.WriteLine(passwordHash3);  
      
      
            bool verified = BCrypt.Net.BCrypt.Verify("Pa$$w0rd", passwordHash1);  
            Console.WriteLine(verified);  
      
            verified = BCrypt.Net.BCrypt.Verify("Pa$$w0rd", passwordHash2);  
            Console.WriteLine(verified);  
      
            verified = BCrypt.Net.BCrypt.Verify("Pa$$w0rd", passwordHash3);  
            Console.WriteLine(verified);  
      
        }  
    

    Sample output

    $2a$11$ensk/K1/bAwu28pGHQm9L.SvS4kB384KYZ3YXwZxz0yoJlxu7nBd6  
    $2a$11$QulSIsv5jhSw1z/6DwnoZei2hdpj2VFsMHofSSGnIrBq7gg7hTnW2  
    $2a$11$15iaamHdIR0PKSgNwTciBe9YSUWw9.vV4Eugs9.r001hMEMi9UQvS  
    True  
    True  
    True  
    

    Reference
    https://jasonwatmore.com/post/2022/01/16/net-6-hash-and-verify-passwords-with-bcrypt

    2 people found this answer helpful.

  2. AgaveJoe 26,191 Reputation points
    2022-07-25T20:41:37.757+00:00

    According to the documentation, the salt is part of the results from HashPassword(). If you did not create a salt then you are using the default salt created by HashPassword(). I have no idea as I cannot see your code.

    The steps should be very simple. Get the hash and store the hash in the database along with the username so you can fetch the hash later.

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

    To validate the login, fetch the hash from the database using the username then validate the hash.

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

    The salt is stored in the front of the hash string. If you look at my example I removed the first character in the string which caused the salt error.

    bool verified = BCrypt.Net.BCrypt.Verify("Pa$$w0rd", passwordHash1.Substring(1, passwordHash1.Length-1));  
    

    Anyway, if you followed the simple steps above and still get a salt error then I assume there is something else wrong with your code. It could be how the hash is passed, saved, or fetched. You also mentioned a proxy but have not explained how the proxy handles the hash.

    You'll need to troubleshoot your code now that you have a better understanding of how BCrypt works.

    2 people found this answer helpful.

  3. JasonPan - MSFT 4,201 Reputation points Microsoft Vendor
    2022-07-25T02:33:24.86+00:00

    Hi @Volk Volk

    I tested this BCrypt and found that if our password contains uppercase letters, the two generated hashPassword will not match.

    Workaround

    Change your code like :

    var hashPassword = BCrypt.Net.BCrypt.HashPassword(password.ToLower());  
    

    When you create pwd or valid it, you can convert to lowercase.

    It seems a bug in BCrypt, I am not sure whether it was fixed. You can upgrade it to latest version to check it. If not fixed, you can convert the password to lowercase.


    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best Regards,
    Jason


  4. Volk Volk 571 Reputation points
    2022-07-25T17:01:02.073+00:00

    I found this: How to decrypt PasswordHash to readable password in Asp.Net 5 Mvc 6

    how-to-decrypt-passwordhash-to-readable-password-in-aspnet-5-mvc-6
    As a result, it says there that I cannot decrypt this password. But I don't need to decrypt it. On the contrary, I need to encrypt it in the same way and just find it in the table.

    The user sends the password to the server. The server must encrypt it in the same way that Net Core 6 MVC website encrypt it. And find this password in the table ASPnetUsers.PasswordHash.

    Where does the site encrypt the user's password and in what way?
    I need to encrypt the user's password in the same way and find it in the table.

    0 comments No comments