BCrypt Проверить сохраненный хэш пароля

Сохранение хешированного пароля в базе данных прошло успешно. Но при проверке, хранится ли входной пароль и хеш в базе данных, он всегда возвращает 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

1 ответ

Решение

Особенно, когда речь идет о шифровании, вы должны иметь общее представление о принципах и концепциях. Соленое хеширование паролей объясняет типичные ошибки и дает ряд рекомендаций (один BCryptтак что вы можете быть на правильном пути).

Похоже, вы не читаете сохраненный хэш из БД, прежде чем проверять. Вы не показываете, как оно сохраняется, но это важно для его проверки.

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

Создать новый вход

' 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

Подтвердить попытку

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

Заметки

  • DbConnection, DbCommand а также DbDataReader все реализовать Dispose Это означает, что они могут очень хорошо распределять ресурсы, которые должны быть освобождены. Код использует каждый из них в Using блок. Это создает их в начале и избавляется от них в конце блока.
  • Это использует электронную почту для уникального идентификатора, потому что там много Стивов. Это означает, что SQL вернет максимум одну запись.
  • После загрузки хешированного pw из БД используйте его для проверки введенной попытки ввода пароля. Ваш код, кажется, создает новый хэш (и фактически ничего не загружает из БД).

Случайная соль, изначально созданная при создании учетной записи, становится частью хэша (а также используемого вами рабочего фактора), как показано здесь:

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

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

Выход:

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

12 после "$2a$" это фактор работы.

Другие вопросы по тегам