NodeJS:如何生成像C#这样的Rfc2898DeriveBytes?
我试图使用NodeJS加密库和C#Rfc2898DeriveBytes生成相同的密码哈希。当使用从C#生成的salt时,NodeJs实现不会生成相同的密钥。我做错了什么? 在C#中: 在NodeJs中:NodeJS:如何生成像C#这样的Rfc2898DeriveBytes?,c#,node.js,C#,Node.js,我试图使用NodeJS加密库和C#Rfc2898DeriveBytes生成相同的密码哈希。当使用从C#生成的salt时,NodeJs实现不会生成相同的密钥。我做错了什么? 在C#中: 在NodeJs中: export const hash = (text, salt) => new Promise((resolve, reject) => { crypto.pbkdf2(text, salt, iterations, bytes, 'sha256', function (err,
export const hash = (text, salt) => new Promise((resolve, reject) => {
crypto.pbkdf2(text, salt, iterations, bytes, 'sha256', function (err, derivedKey) {
if (err) { reject(err) }
else {
//return Pbkdf2Iterations + ":" + Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);
var hash = new Buffer(derivedKey).toString('base64');
var pass = `${iterations}:${salt}:${hash}`
resolve(pass);
}});})
然后像这样使用:
var a = Buffer.from("qcMqVYE0EzAU9Uz+mQxBaKFICG1vR1iq", 'base64')
var a0 = new Buffer("qcMqVYE0EzAU9Uz+mQxBaKFICG1vR1iq")
var pas1 = new Buffer('AL7h8Jx4r8a8PjS5', 'base64')
hash(pas1,a0).then(pass => {
console.log("pass: ", pass)
const hashes = crypto.getHashes();
console.log(hashes); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...]
res.send(pass + "\n1000:qcMqVYE0EzAU9Uz+mQxBaKFICG1vR1iq:RkdpgAcpijFqYgVxBCvJugMXqnt4j5f3")
})
正如你所看到的,哈斯在C#中传球,而诺德斯则不同。
节点->
1000:qcMqVYE0EzAU9Uz+mQxBaKFICG1vR1iq:D19SUxg6AQxgSLe7YXISPWPvgIoR6BEw
C#->
1000:qcMqVYE0EzAU9Uz+mQxBaKFICG1vR1iq:RKDPGACIPIJFQYGVBCVJUGMXQNT4J5F3
我有一个非常相似的问题,事实上你的发现对我帮助很大。 看起来唯一的问题是传递给pbkdf2函数的哈希算法错误 看起来Rfc2898DeriveBytes默认使用SHA1。因此,您应该像在node中那样使用smth:
crypto.pbkdf2(text, salt, iterations, bytes, 'sha1', (err, key) => {
console.log(key.toString('hex'));
});
在这里我输入了FixSalt,还可以生成16个随机字符串。你也可以改变长度而不是我的“32” 要将存储的哈希密码与用户inpur密码匹配,请使用以下代码:
// NodeJS implementation of crypto, I'm sure google's
// cryptoJS would work equally well.
var crypto = require('crypto');
// The value stored in [dbo].[AspNetUsers].[PasswordHash]
var hashedPwd = "AGYzaTk3eldHaXkxbDlkQmn+mVJZEjd+0oOcLTNvSQ+lvUQIF1u1CNMs+WjXEzOYNg==";
var hashedPasswordBytes = new Buffer(hashedPwd, 'base64');
var hexChar = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
var saltString = "";
var storedSubKeyString = "";
// build strings of octets for the salt and the stored key
for (var i = 1; i < hashedPasswordBytes.length; i++) {
if (i > 0 && i <= 16) {
saltString += hexChar[(hashedPasswordBytes[i] >> 4) & 0x0f] + hexChar[hashedPasswordBytes[i] & 0x0f]
}
if (i > 0 && i > 16) {
storedSubKeyString += hexChar[(hashedPasswordBytes[i] >> 4) & 0x0f] + hexChar[hashedPasswordBytes[i] & 0x0f];
}
}
// password provided by the user
var password = 'vish@123';
// TODO remove debug - logging passwords in prod is considered
// tasteless for some odd reason
console.log('cleartext: ' + password);
console.log('saltString: ' + saltString);
console.log('storedSubKeyString: ' + storedSubKeyString);
// This is where the magic happens.
// If you are doing your own hashing, you can (and maybe should)
// perform more iterations of applying the salt and perhaps
// use a stronger hash than sha1, but if you want it to work
// with the [as of 2015] Microsoft Identity framework, keep
// these settings.
var nodeCrypto = crypto.pbkdf2Sync(new Buffer(password), new Buffer(saltString, 'hex'), 1000, 256, 'sha1');
// get a hex string of the derived bytes
var derivedKeyOctets = nodeCrypto.toString('hex').toUpperCase();
console.log("hex of derived key octets: " + derivedKeyOctets);
// The first 64 bytes of the derived key should
// match the stored sub key
if (derivedKeyOctets.indexOf(storedSubKeyString) === 0) {
console.info("passwords match!");
} else {
console.warn("passwords DO NOT match!");
}
//NodeJS实现加密,我相信谷歌
//cryptoJS也同样有效。
var crypto=require('crypto');
//存储在[dbo].[AspNetUsers].[PasswordHash]中的值
var hashedPwd=“agyzatk3eldhakxbdlkqmn+mVJZEjd+0oOcLTNvSQ+lvUQIF1u1CNMs+WjXEzOYNg=”;
var hashedPasswordBytes=新缓冲区(hashedPwd,'base64');
var hexChar=[“0”、“1”、“2”、“3”、“4”、“5”、“6”、“7”、“8”、“9”、“A”、“B”、“C”、“D”、“E”、“F”];
var saltString=“”;
var storedSubKeyString=“”;
//为salt和存储的密钥构建八进制字符串
对于(var i=1;i0&&i>4)&0x0f]+hexChar[hashedPasswordBytes[i]&0x0f]
}
如果(i>0&&i>16){
storedSubKeyString+=hexChar[(hashedPasswordBytes[i]>>4)&0x0f]+hexChar[hashedPasswordBytes[i]&0x0f];
}
}
//用户提供的密码
var密码=vish@123';
//TODO删除调试-考虑在prod中记录密码
//因为某种奇怪的原因而无味
log('cleartext:'+密码);
log('saltString:'+saltString);
log('storedSubKeyString:'+storedSubKeyString);
//这就是魔法发生的地方。
//如果你正在做你自己的散列,你可以(也许应该)
//执行更多的应用盐的迭代,也许
//使用比sha1更强大的散列,但是如果你想让它工作的话
//使用[截至2015年]的Microsoft Identity framework
//这些设置。
var nodeCrypto=crypto.pbkdf2Sync(新缓冲区(密码),新缓冲区(saltString,'hex'),1000256,'sha1');
//获取派生字节的十六进制字符串
var derivedKeyOctets=nodeCrypto.toString('hex').toUpperCase();
log(“派生密钥八位字节的十六进制:“+derivedKeyOctets”);
//派生密钥的前64个字节应为
//匹配存储的子密钥
if(derivedKeyOctets.indexOf(storedSubKeyString)==0){
console.info(“密码匹配!”);
}否则{
控制台。警告(“密码不匹配!”);
}
var crypto = require('crypto');
salt = '1234123412341234';
saltString = new Buffer(salt).toString('hex');
var password = 'welcome';
var nodeCrypto = crypto.pbkdf2Sync(new Buffer(password), new Buffer(saltString, 'hex'), 1000, 32, 'sha1');
var hashInHex="00"+saltString+nodeCrypto.toString('hex').toUpperCase();
var FinalHash = Buffer.from(hashInHex, 'hex').toString('base64')
console.log("saltInHex: "+saltString);
console.log("FinalHashInBase64: "+FinalHash);
// NodeJS implementation of crypto, I'm sure google's
// cryptoJS would work equally well.
var crypto = require('crypto');
// The value stored in [dbo].[AspNetUsers].[PasswordHash]
var hashedPwd = "AGYzaTk3eldHaXkxbDlkQmn+mVJZEjd+0oOcLTNvSQ+lvUQIF1u1CNMs+WjXEzOYNg==";
var hashedPasswordBytes = new Buffer(hashedPwd, 'base64');
var hexChar = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
var saltString = "";
var storedSubKeyString = "";
// build strings of octets for the salt and the stored key
for (var i = 1; i < hashedPasswordBytes.length; i++) {
if (i > 0 && i <= 16) {
saltString += hexChar[(hashedPasswordBytes[i] >> 4) & 0x0f] + hexChar[hashedPasswordBytes[i] & 0x0f]
}
if (i > 0 && i > 16) {
storedSubKeyString += hexChar[(hashedPasswordBytes[i] >> 4) & 0x0f] + hexChar[hashedPasswordBytes[i] & 0x0f];
}
}
// password provided by the user
var password = 'vish@123';
// TODO remove debug - logging passwords in prod is considered
// tasteless for some odd reason
console.log('cleartext: ' + password);
console.log('saltString: ' + saltString);
console.log('storedSubKeyString: ' + storedSubKeyString);
// This is where the magic happens.
// If you are doing your own hashing, you can (and maybe should)
// perform more iterations of applying the salt and perhaps
// use a stronger hash than sha1, but if you want it to work
// with the [as of 2015] Microsoft Identity framework, keep
// these settings.
var nodeCrypto = crypto.pbkdf2Sync(new Buffer(password), new Buffer(saltString, 'hex'), 1000, 256, 'sha1');
// get a hex string of the derived bytes
var derivedKeyOctets = nodeCrypto.toString('hex').toUpperCase();
console.log("hex of derived key octets: " + derivedKeyOctets);
// The first 64 bytes of the derived key should
// match the stored sub key
if (derivedKeyOctets.indexOf(storedSubKeyString) === 0) {
console.info("passwords match!");
} else {
console.warn("passwords DO NOT match!");
}