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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…