我正在使用libsodium的 .net 端口。哈希生成函数有两种形式,一种接受字节数组,一种接受字符串:
public static byte[] ArgonHashBinary(string password, string salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES)
public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES)
我遇到的问题是当输入值相同时,两个表单产生相同的哈希值。
var saltAsBytes = PasswordHash.ArgonGenerateSalt();
var saltAsString = Encoding.UTF8.GetString(saltAsBytes);
var tmp = Encoding.UTF8.GetBytes(saltAsString);
var hash1 = PasswordHash.ArgonHashBinary(password, saltAsString, 6, 134217728, 16);
var hash2 = PasswordHash.ArgonHashBinary( Encoding.UTF8.GetBytes(password), saltAsBytes, 6, 134217728, 16);
"PasswordHash."开头的内容都是libsodium而不是我的代码。
从上面的代码中,当我将其从字符串转换为字节数组,然后再将其转换回来时,字节数组的长度总是不同的。ArgonGenerateSalt()
生成一个长度为16的字节数组。当我将其从上面的字符串转换回来时,它通常是 ~30(每次因生成不同盐而不同)。
为什么要转换为UTF8?因为这是它们在内部所做的事情: https://github.com/adamcaudill/libsodium-net/blob/master/libsodium-net/PasswordHash.cs
public static byte[] ArgonHashBinary(string password, string salt, StrengthArgon limit = StrengthArgon.Interactive, long outputLength = ARGON_SALTBYTES)
{
return ArgonHashBinary(Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), limit, outputLength);
}
当我将盐转换为UTF8字符串时,哈希函数会失败,因为它们检查字节数组的长度以确保其为16个字节。如果我将其转换为ASCII字符串,则可以工作,但会产生不同的哈希值(这是预期的)。
需要澄清的是,此代码中的哈希部分不是问题所在。找出为什么“tmp”与“saltAsBytes”不同是关键。
PasswordHash
中的代码,以查看问题出在哪里? - Jim Mischelvar bytes = new byte[] { 255, 255, 255 }; var buf = Encoding.Unicode.GetString(bytes); var newbytes = Encoding.Unicode.GetBytes(buf); var n = String.Join(", ", newbytes);
返回 255,255,253,255 - H.G. Sandhagen