[mysql]BCrypt 验证存储密码哈希

标签: Vb.net MySQL .Net
发布时间: 2017/4/8 13:45:47
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

在数据库中存储的哈希的密码是成功的。但在验证时如果输入的密码和哈希值存储在数据库中,它总是返回 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 ,所以你可能会在正确的道路)。

看起来你不读存储的哈希从 DB 之前您验证。 你不显示它的保存方式,但这是重要的为了它来验证。

 ' 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

备注

  • DbConnectionDbCommandDbDataReader 都实现 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$" 是工作的因素。

赞助商