Hash加密是不可逆的,这样哪怕数据库被窃取,对方也无法获取到用户密码。
那么登录时如何校验用户密码是否正确呢?
其实很简单,就是再使用Hash加密一次,校验加密后的数据是否一致。
如果有用户密码设置一样,那么加密后的结果也是一样的,为了避免这种情况,使用Hash加密时可以采用随机数的方案,增加一个salt。
其中:
Hash(哈希值):密码经过不可逆计算后的结果。
Salt(盐值):随机生成的一段数据,用来参与密码哈希计算。
简单来说:
Hash = Hash算法(密码 + Salt);
一、数据表的结构
为了保证每次加密结果一样,首次加密使用的salt要保存下来。
| 字段名 | 字段类型 | 字段释义 |
|---|---|---|
| id | int | 用户id |
| account | string | 账号 |
| passwordHash | string | 密码Hash |
| passwordSalt | string | 密码salt |
二、Hash加密
老规矩,直接上代码
/// <summary>
/// 密码工具类
/// </summary>
public static class PasswordHelper
{
/// <summary>
/// 获取16位随机数
/// </summary>
/// <returns></returns>
public static string GenerateSalt()
{
byte[] salt = new byte[16];
RandomNumberGenerator.Fill(salt);
return Convert.ToBase64String(salt);
}
/// <summary>
/// 获取密码hash
/// </summary>
/// <param name="password"></param>
/// <param name="salt"></param>
/// <returns></returns>
public static string HashPassword(string password, string salt)
{
byte[] saltBytes = Convert.FromBase64String(salt);
using(var pbkdf2 = new Rfc2898DeriveBytes(
password,
saltBytes,
100000,
HashAlgorithmName.SHA256))
{
return Convert.ToBase64String(pbkdf2.GetBytes(32));
}
}
/// <summary>
/// 校验密码
/// </summary>
/// <param name="inputPassword"></param>
/// <param name="storedHash"></param>
/// <param name="storedSalt"></param>
/// <returns></returns>
public static bool VerifyPassword(string inputPassword, string storedHash, string storedSalt)
{
byte[] inputHash = Convert.FromBase64String(HashPassword(inputPassword, storedSalt));
byte[] dbHash = Convert.FromBase64String(storedHash);
return CryptographicOperations.FixedTimeEquals(inputHash, dbHash);
}
}
三、创建用户
以下是伪代码。
void inserUser()
{
string salt = PasswordHelper.GenerateSalt();
string hash = PasswordHelper.HashPassword("testmima123", salt);
// 创建用户
User user = new User
{
account = "acount123",
passwordHash = hash,
passwordSalt = salt,
};
//插入
InsertUser(user);
}
四、校验密码
以下是伪代码。
bool ok = PasswordHelper.VerifyPassword(
"testmima123", // 用户登录时输入的密码
user.PasswordHash, // 创建用户时保存的数据
user.PasswordSalt// 创建用户时保存的数据
);
if(ok){
Console.WritLine("校验通过");
}else{
Console.WritLine("输入密码错误");
}
如此,数据库就不会保存明文密码啦。
感谢看完全文,比心!

1433

被折叠的 条评论
为什么被折叠?



