将哈希密码存储在数据库中是成功的。但是在验证输入密码和存储在数据库中的哈希时,它总是返回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
答案 0 :(得分:2)
特别是在加密方面,您应该对所涉及的原则和概念有一些大致的了解。 Salted Password Hashing解释了常见的陷阱并提出了一些建议(一个是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
块中使用它们中的每一个。这会在开始时创建它们,并在块的末尾处理它们。创建帐户时最初生成的随机盐会成为散列的一部分(以及您使用的工作因素),如下所示:
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$"
是工作因素。