将密码哈希函数从Python移植到.NET 8
我们有一个用Python写的旧软件系统,它使用了以下的密码哈希函数:
import hashlib, binascii, os
def hash_password(password):
"""Hash a password for storing."""
salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
pwdhash = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'),
salt, 100000)
pwdhash = binascii.hexlify(pwdhash)
return (salt + pwdhash).decode('ascii')
def verify_password(stored_password, provided_password):
"""Verify a stored password against one provided by user"""
salt = stored_password[:64]
stored_password = stored_password[64:]
pwdhash = hashlib.pbkdf2_hmac('sha512',
provided_password.encode('utf-8'),
salt.encode('ascii'),
100000)
pwdhash = binascii.hexlify(pwdhash).decode('ascii')
return pwdhash == stored_password
我们尝试把这段代码迁移到.NET 8,但结果不对。
在Python生成的哈希值和在C#生成的哈希值不一样。
有没有人知道我们的方法哪里出了问题?
这是我们尝试过的:
public string HashPassword(string password)
{
var salt = Encoding.ASCII.GetBytes(GenerateRandomString(60));
using var pbkdf2 = new Rfc2898DeriveBytes(
Encoding.UTF8.GetBytes(password),
salt,
100000,
HashAlgorithmName.SHA512);
var hashedPassword = pbkdf2.GetBytes(64);
return Encoding.ASCII.GetString(salt.Concat(hashedPassword).ToArray());
}
public bool VerifyPassword(string password, string hash)
{
var salt = hash[..64];
var passwordHash = Encoding.UTF8.GetBytes(hash[64..]);
using var pbkdf2 = new Rfc2898DeriveBytes(
Encoding.UTF8.GetBytes(password),
Encoding.ASCII.GetBytes(salt),
100000,
HashAlgorithmName.SHA512);
var hashedPassword = pbkdf2.GetBytes(64);
return hashedPassword.SequenceEqual(passwordHash);
}
private string GenerateRandomString(int length)
{
var sb = new StringBuilder();
var random = new Random();
for (int i = 0; i < length; i++)
{
double flt = random.NextDouble();
int shift = Convert.ToInt32(Math.Floor(25 * flt));
char letter = Convert.ToChar(shift + 65);
sb.Append(letter);
}
return sb.ToString();
}
1 个回答
0
谢谢你的帮助。我找到了解决办法。
public string HashPassword(string password)
{
var salt = HexDigest(SHA256.HashData(RandomNumberGenerator.GetBytes(30)));
var hashedPassword = ComputeHmacSha512Hash(password, salt);
return salt + HexDigest(hashedPassword);
}
public bool VerifyPassword(string passwordToVerify, string saltPasswordHash)
{
var salt = saltPasswordHash[..64];
var password = saltPasswordHash[64..];
var hashedPassword = ComputeHmacSha512Hash(passwordToVerify, salt);
return password.SequenceEqual(HexDigest(hashedPassword));
}
private static byte[] ComputeHmacSha512Hash(string password, string salt)
{
using var pbkdf2 = new Rfc2898DeriveBytes(
Encoding.UTF8.GetBytes(password),
Encoding.ASCII.GetBytes(salt),
100000,
HashAlgorithmName.SHA512);
return pbkdf2.GetBytes(64);
}
private static string HexDigest(byte[] bytes)
{
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}