Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

mysql - BCrypt Verify stored password hash

Storing the hashed password in database is successful. But when verifying if the input password and the hash stored in database, it always returning false.

    Dim pw As String = txt_password.Text
    Dim salt As String = BCrypt.Net.BCrypt.GenerateSalt(12)
    Dim hash As String = BCrypt.Net.BCrypt.HashPassword(pw, salt)

    With sqlLogin
            .Parameters.AddWithValue("@userid", txt_username.Text)
            .Parameters.AddWithValue("@userpass", hash)
    End With

                Dim Reader As MySqlDataReader = sqlLogin.ExecuteReader()
            If (BCrypt.Net.BCrypt.Verify(pw, hash)) Then
                MessageBox.Show("Login Succesful!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Me.Hide()
                Reader.Close()
            ElseIf Reader.HasRows = False Then
                MessageBox.Show("Invalid Login Information!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                txt_username.Text = ""
                txt_password.Text = ""
                txt_username.Focus())
            End If
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Especially when it comes to encryption, you ought to have some general idea of the principles and concepts involved. Salted Password Hashing explains common pitfalls and makes a number of recommendations (one is BCrypt, so you may be on the right path).

It looks like you are not reading the stored hash from the DB before you verify. You don't show how it is saved, but that is important in order for it to verify.

 ' cuts down on dot operators
 Imports BCryptor = BCrypt.Net.BCrypt

Create New Logon

' new user save
Dim sql = "INSERT INTO userlogin (email, username, pwhash) VALUES (@email, @n, @pw)"
' prep:
Dim salt = BCryptor.GenerateSalt(12)    ' == 2^12
Dim hash = BCryptor.HashPassword(tbPass)

' to do: Try/Catch for an email that already exists
Using dbCon As New MySqlConnection(MySQLConnStr),
    cmd As New MySqlCommand(sql, dbCon)

    cmd.Parameters.Add("@email", MySqlDbType.Text).Value = tbEmail
    cmd.Parameters.Add("@n", MySqlDbType.Text).Value = tbUserName
    cmd.Parameters.Add("@pw", MySqlDbType.Text).Value = hash
    dbCon.Open()
    cmd.ExecuteNonQuery()

End Using

Verify an Attempt

Dim bRet As Boolean = False

' login user 
Dim sql = "SELECT pwhash FROM userlogin WHERE email = @email"

Using dbCon As New MySqlConnection(MySQLConnStr),
        cmd As New MySqlCommand(sql, dbCon)

    ' data for the where clause
    cmd.Parameters.Add("@email", MySqlDbType.Text).Value = tbEmail

    dbCon.Open()
    Using rdr = cmd.ExecuteReader()
       ' read from the reader to load data
        If rdr.Read() Then
            ' get the saved hash
            Dim savedHash = rdr.GetString(0)
            bRet = BCryptor.Verify(tbPass, savedHash)
        Else
            bRet = False
        End If
    End Using
    ' return whether the hash verified
    Return ret
End Using

Notes

  • DbConnection, DbCommand and DbDataReader all implement Dispose which means they may very well allocate resources which need to be released. The code uses each of them in a Using block. This creates them at the start and disposes of them at the end of the Block.
  • This uses an email for the unique identifier because there are a lot of Steves out there. This means the SQL will return one record at most.
  • After loading the hashed pw from the DB, use it to verify the password attempt entered. Your code seems to be creating a new hash (and doesnt actually load anything from the DB).

The random salt originally generated when the account was created becomes part of the hash (as well as the work factor you used) as shown here:

Dim pw = "My!Weak#Pa$$word"
Dim salt = BCryptor.GenerateSalt(12)
Dim hash = BCryptor.HashPassword(pw, salt)

Console.WriteLine(salt)
Console.WriteLine(hash)

Output:

$2a$12$XPC20niJIhZPxaKvJkSUfO
$2a$12$XPC20niJIhZPxaKvJkSUfO/rwIetoScCze.tOcVS/aJzowvjpCPlq

The 12 after "$2a$" is the work factor.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...