Invalid salt version error in BCrypt.Net library - WinForms/C# application with MySQL DB

Viewed 8084

I am currently making a password manager, therefore I make a log-in form with username and password fields. I want to bcrypt the password. I store the salt and the hashed password in the database (screenshot 1). When the user enters their username and password what I do is:

1.Retrieve the salt from the DB and use the BCrypt.Net.BCrypt.HashPassword(password.Text, sal) method to hash the submitted password with the salt from the database

2.Retrieve the original hashed password from the db table, and then use the method BCrypt.Net.BCrypt.Verify(submhash, passdb) to check if the 2 passwords hashes match.

3.If they do match I open the main form of the program.

However the VS Studio throws an exception : Invalid salt version ( screenshot 2)

I would like to ask where is the problem and how can I fix it?

            conn.Open();
            MySqlCommand cmd = new MySqlCommand();
            cmd.Connection = conn;
            cmd.Parameters.AddWithValue("@usr", username.Text);
           // cmd.Parameters.AddWithValue("@pas", password.Text);
            cmd.CommandText = "select password from users where username = @usr";
            passdb = (string)cmd.ExecuteScalar();
            MySqlCommand ss = new MySqlCommand();
            ss.Connection = conn;
            ss.Parameters.AddWithValue("@uun", username.Text);
            ss.CommandText = "select salt from users where username  = @uun";
            sal= (string)ss.ExecuteScalar();
            submhash = BCrypt.Net.BCrypt.HashPassword(password.Text, sal);
            MySqlCommand com = new MySqlCommand();
            com.Connection = conn;
            com.Parameters.AddWithValue("@unm", username.Text);
            if (BCrypt.Net.BCrypt.Verify(submhash, passdb))
            {
                frmMain fm = new frmMain();
                SesUser.username = username.Text;
                SesUser.password = password.Text;
                this.Hide();
                fm.Show();


            }
            else
            {
                MessageBox.Show("Username or password is incorrect!","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                i++;

            }

        }
4 Answers

First you should wrap MySqlCommand inside a using statement, because DbCommand implements IDisposable.

Regarding your BCrypt issue.

You do not have to create a new hash and compare it to the saved hashed value. Because every time you do this you'll get a different hash. You just have to verify a password against a saved hash with BCrypt.Net.

So the following should work

if (BCrypt.Net.BCrypt.Verify(password.Text, passdb))
{
  // logged in
}
// not logged in

I'm expecting that passdb holds a bcrypt hash like the folowing:

$2a$12$VvDRKYKGt4Zd2Ux35LeG2OI.Vr5f.UuY2q7MrnHlJj4K5diifQV3e

I encountered this error when there was an invalid character in the 'prefix' of the encrypted string that bcrypt was supposed to hash/verify. Make sure your bcrypt function input string starts with a correct bcrypt version and salt length (ex: $2b$10) as shown in this wikipedia article.

I would check the 'sal' string in your code to ensure it contains the proper hashing revision (starts with that $2b$xyz sequence)

int salt = 12;
string passwordHash = BCrypt.Net.BCrypt.HashPassword(enteredpassword, salt);
bool correctPassword = BCrypt.Net.BCrypt.Verify(storedPassword, passwordHash);
    

I swapped passwordHash and storedPassword and correctPassword was true and program worked.

I've hit this issue too. In general with BCrypt you shouldn't have to handle the salt yourself and the library advises you to just let them generate it for you:

Note: Although this library allows you to supply your own salt, it is highly advisable that you allow the library to generate the salt for you. These methods are supplied to maintain compatibility and for more advanced cross-platform requirements that may necessitate their use.

After a lot of poking it turned out I was doing something very simple and very stupid - I'd passed the arguments in the wrong order. I've seen a few other questions on this topic floating around the internet, and for me digging into the library code itself was a rabbit hole - the problem was much more simple. Thus I'd recommend that if you are thinking about explicitly generating/handling a BCrypt salt yourself to solve a problem like this, look carefully for bugs in your implementation first.

Another key thing to note - if you do:

dotnet add package BCrypt.Net

Then at the time of writing I got BCrypt.Net 0.1.0, where the release I was expecting was 4.0.0. The correct package is called BCrypt.Net-Next:

dotnet add package BCrypt.Net-Next --version 4.0.0

Seemed to get the correct library.

The OP should consider disposing of IDisposables and selecting the salt and password in a single query since they're both in the same table to prevent extra roundtrips to the database.

Related