Encoding.UTF8转换哈希/盐字节数组后值不一致的原因及解决
哈希/盐字节数组转字符串后无法还原的问题分析与解决
问题原因
UTF-8编码是用来处理符合Unicode标准的文本字符的,不是用来表示任意二进制字节序列的。HMAC生成的盐和哈希是纯二进制数据,里面肯定有很多无法被UTF-8识别为有效字符的字节。当你调用Encoding.UTF8.GetString()时,这些无效字节会被自动替换成通用替换字符(�),原始字节的信息直接就丢了。之后再用Encoding.UTF8.GetBytes()转回去,替换字符对应的字节和原始字节完全不一样,自然得不到和原数组一致的结果。
修正方案
改用Base64编码来做字节数组和字符串的转换——Base64就是专门为二进制数据的文本化表示设计的,能保证数据完整可逆。修改后的代码如下:
string password = "xxx"; byte[] pswSalt; byte[] pswHash; using (HMACSHA512 hmac = new HMACSHA512()) { pswSalt = hmac.Key; pswHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)); } // 将字节数组转为Base64字符串 var saltAsString = Convert.ToBase64String(pswSalt); var hashAsString = Convert.ToBase64String(pswHash); // 将Base64字符串转回字节数组 var pswSaltFromString = Convert.FromBase64String(saltAsString); var pswHashFromString = Convert.FromBase64String(hashAsString);
现在验证的话,转换后的字节数组和原始数组会完全一致,因为Base64编码不会丢失任何二进制信息,这也是存储、传输哈希、盐这类二进制数据的标准做法。
内容的提问来源于stack exchange,提问作者Val
相关产品推荐
相关产品推荐

