相同的密码哈希不匹配
Same password hash not matching
我正在尝试使用 C# 创建和测试我的 api 登录。以下是代码的主要部分:
private static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (var hmac = new HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}
private static bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (var hmac = new HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
return computedHash.SequenceEqual(passwordHash);
}
}
我的 Db 是 Mysql 8,CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci 格式。
值存储为 varchar(512),因此在保存时长度不是问题。
保存数据的DB部分代码为:
Cmd.Parameters.Add(new MySqlParameter("@username", MySqlDbType.VarChar)).Value = user.UserName;
Cmd.Parameters.Add(new MySqlParameter("@passwordhash", MySqlDbType.VarChar)).Value = Convert.ToBase64String(user.PasswordHash);
Cmd.Parameters.Add(new MySqlParameter("@passwordsalt", MySqlDbType.VarChar)).Value = Convert.ToBase64String(user.PasswordSalt);
从数据库中检索数据以进行密码检查的代码是:
while (Rdr.Read() == true)
{
user.UserName = Rdr.GetString("username");
user.PasswordHash = System.Text.Encoding.UTF8.GetBytes(Rdr.GetString("passwordhash"));
user.PasswordSalt = System.Text.Encoding.UTF8.GetBytes(Rdr.GetString("passwordsalt"));
user.UserID = Rdr.GetInt16("userid");
}
Rdr.Close();
但是我在做密码匹配的时候,总是匹配不上,请问是哪里做错了,是不是编码等问题
VerifyPasswordHash(request.Password, user.PasswordHash, user.PasswordSalt)
从 tutorial 学习代码,但教程来自 DB 提取,所以想知道我在这个过程中是否做错了什么导致它不匹配。
我认为您需要使用 Convert.FromBase64String
.
转换回哈希和盐
while (Rdr.Read() == true)
{
user.UserName = Rdr.GetString("username");
user.PasswordHash = Convert.FromBase64String(Rdr.GetString("passwordhash"));
user.PasswordSalt = Convert.FromBase64String(Rdr.GetString("passwordsalt"));
user.UserID = Rdr.GetInt16("userid");
}
Rdr.Close();
这是存储密码哈希值的错误方法,使用普通硬件计算它的速度可能太快(每秒几千兆 SHA512)。因此你需要一个像 BCrypt 或 Argon2 这样的 password-hash 函数,它有一个成本因素来控制单个计算的必要时间。
BCrypt 库 https://www.nuget.org/packages/BCrypt.Net-Next/ 是一个不错的选择。它还将 includes/extracts 盐放入生成的 password-hash 字符串中,因此您只需要一个数据库字段来存储哈希值。
我正在尝试使用 C# 创建和测试我的 api 登录。以下是代码的主要部分:
private static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (var hmac = new HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}
private static bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (var hmac = new HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
return computedHash.SequenceEqual(passwordHash);
}
}
我的 Db 是 Mysql 8,CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci 格式。 值存储为 varchar(512),因此在保存时长度不是问题。
保存数据的DB部分代码为:
Cmd.Parameters.Add(new MySqlParameter("@username", MySqlDbType.VarChar)).Value = user.UserName;
Cmd.Parameters.Add(new MySqlParameter("@passwordhash", MySqlDbType.VarChar)).Value = Convert.ToBase64String(user.PasswordHash);
Cmd.Parameters.Add(new MySqlParameter("@passwordsalt", MySqlDbType.VarChar)).Value = Convert.ToBase64String(user.PasswordSalt);
从数据库中检索数据以进行密码检查的代码是:
while (Rdr.Read() == true)
{
user.UserName = Rdr.GetString("username");
user.PasswordHash = System.Text.Encoding.UTF8.GetBytes(Rdr.GetString("passwordhash"));
user.PasswordSalt = System.Text.Encoding.UTF8.GetBytes(Rdr.GetString("passwordsalt"));
user.UserID = Rdr.GetInt16("userid");
}
Rdr.Close();
但是我在做密码匹配的时候,总是匹配不上,请问是哪里做错了,是不是编码等问题
VerifyPasswordHash(request.Password, user.PasswordHash, user.PasswordSalt)
从 tutorial 学习代码,但教程来自 DB 提取,所以想知道我在这个过程中是否做错了什么导致它不匹配。
我认为您需要使用 Convert.FromBase64String
.
while (Rdr.Read() == true)
{
user.UserName = Rdr.GetString("username");
user.PasswordHash = Convert.FromBase64String(Rdr.GetString("passwordhash"));
user.PasswordSalt = Convert.FromBase64String(Rdr.GetString("passwordsalt"));
user.UserID = Rdr.GetInt16("userid");
}
Rdr.Close();
这是存储密码哈希值的错误方法,使用普通硬件计算它的速度可能太快(每秒几千兆 SHA512)。因此你需要一个像 BCrypt 或 Argon2 这样的 password-hash 函数,它有一个成本因素来控制单个计算的必要时间。
BCrypt 库 https://www.nuget.org/packages/BCrypt.Net-Next/ 是一个不错的选择。它还将 includes/extracts 盐放入生成的 password-hash 字符串中,因此您只需要一个数据库字段来存储哈希值。