我尝试使用NodeJS加密库和C#Rfc2898DeriveBytes生成相同的密码哈希。使用NodeJ生成的salt时,C#实现不会生成相同的密钥。我做错了什么?
nodeJS中生成的salt和hash:
Salt: GJNw/wzXZxEdXrheqo322mf0x+92AeAuAHH48iiGZ+A=
Hash: w6fCpsKxw78Fw4pMFk5Zw6vDin7CnG5VwpUWBSjCo8OSOTJ6w47Cv8KWcjIpwoA=
在C#中生成的哈希:
1G84mPkY78nsQ2BzO/qUPd+e0Lobrz7ZLzc+p7Zh0o8=
我的C#测试代码如下:
public const int HASH_BYTE_SIZE = 32;
public const int PBKDF2_ITERATIONS = 1000;
public static string HashPassword(string password, string salt)
{
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] saltBytes = Convert.FromBase64String(salt);
var pbkdf2 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, PBKDF2_ITERATIONS);
var hash = pbkdf2.GetBytes(HASH_BYTE_SIZE);
return Convert.ToBase64String(hash);
}
static void Main(string[] args)
{
string salt = "GJNw/wzXZxEdXrheqo322mf0x+92AeAuAHH48iiGZ+A=";
string plainTextPsw = "12345";
string hashedPsw = PasswordHash.HashPassword(plainTextPsw, salt);
Console.WriteLine(hashedPsw);
Console.ReadLine();
}
和NodeJs:
var crypto = require('crypto');
var iterations = 1000;
var bytes = 32;
exports.createSalt = function () {
return new Buffer(crypto.randomBytes(bytes)).toString('base64');
}
exports.hash = function hash(text, salt, callback) {
crypto.pbkdf2(text, salt, iterations, bytes, function (err, derivedKey) {
if (err) { callback(err); }
else {
var h = new Buffer(derivedKey).toString('base64');
callback(null, h);
}
});
}
答案 0 :(得分:0)
Node.js代码中发生了一些错误的转换,产生了无效的结果。
首先,"盐"传递给pbkdf2函数应该是随机字节,不应用任何转换。但是,在这种情况下,字节用Base64编码为文本,并且该文本中的字符被Node.js用作盐。
然后,派生密钥应使用Base64直接编码为文本。但在这里,密钥的字节被视为字符;使用UTF-8编码将此字符串转换为不同字节的新字符串。然后使用Base64对此编码进行编码,以产生最终的错误结果。