源字节数组到字符串,然后回到字节数组与源不同

本文关键字:数组 到字节 字节 字节数 字符串 然后 | 更新日期: 2023-09-27 18:37:24

我对下一段(简化的)代码感到困惑。在用户注册时,它会加密密码,将哈希转换为字符串并将其保存在数据库中。在该用户尝试登录后,代码从数据库中读取密码,获取密码的字节数,并与用户输入的密码的加密哈希进行比较。

static void Main(string[] args)
{
    //User registration
    byte[] passwordBytes = Encoding.Unicode.GetBytes("P@ssword");
    byte[] hashBytes = GetHash(passwordBytes);
    string stringFieldInDb = Encoding.Unicode.GetString(hashBytes); //password hash is being stored in database

    //Check password
    byte[] hashBytesInDb = Encoding.Unicode.GetBytes(stringFieldInDb); //was read from database
    byte[] enteredPasswordBytes = Encoding.Unicode.GetBytes("P@ssword");
    byte[] enteredPasswordHash = GetHash(enteredPasswordBytes);
    //is false
    var isPasswordValid = hashBytesInDb.SequenceEqual(enteredPasswordHash);
    //this way is true
    var isPasswordValid2 = stringFieldInDb == Encoding.Unicode.GetString(enteredPasswordHash);
}
private static byte[] GetHash(byte[] data)
{
    return new SHA512CryptoServiceProvider().ComputeHash(data);
}
哈希

值略有不同,来自数据库的哈希字符串字节数:

161, 127, 0, 49, 27, 146, **253, 255**, 109, 214, **253, 255**, 113, 75, 226, ...

从登录时输入的密码生成的哈希字符串字节数:

161, 127, 0, 49, 27, 146, **74, 219**, 109, 214, **65, 220**, 113, 75, 226, ...

我将上面的例子缩短为三行,我想知道这个结果是什么原因?

byte[] someCharBytes = new byte[] { 74, 219 };
string someChar = Encoding.Unicode.GetString(someCharBytes);
byte[] differentSomeCharBytes = Encoding.Unicode.GetBytes(someChar); //returns { 253, 255 }

源字节数组到字符串,然后回到字节数组与源不同

您正在做的是尝试将哈希数据(本质上是随机字节)解释为有效的 UTF-16 数据。那行不通。并非所有字节组合都有效。您获得的特定字节253, 255U+FFFD REPLACEMENT CHARACTER 的 UTF-16 表示形式,这是用于通知无效字节序列的字符。

如果需要将字节数组转换为字符串进行存储,base64编码非常流行。查看Convert.ToBase64StringConvert.FromBase64String