我有一个用Python编写的后端应用程序,供我网站的内容管理器使用。使用passlib's pbkdf2_sha512函数对用户密码进行哈希处理。我开始开发前端应用程序,出于UX的原因,我决定将其与React一起使用nodejs。
现在我的问题是我不知道如何使用nodejs验证用户的身份验证passlib散列的密码。 Passlib的实现对我来说似乎太具体了,我并不真正喜欢加密的东西。
我有MCF,所以我知道算法和摘要类型,盐,迭代次数和密钥长度。如何验证节点中passlib的输出?我是否应该选择两个平台都更好地支持的另一种算法?
最佳答案
我们遇到了完全相同的问题,但没有选择切换到sha512crypt。在我们的情况下,密码是通过flask-security生成的。下面的示例涵盖常规的passlib和flask-security哈希,它们首先生成带有秘密盐的HMAC,并将其用作pbkdf2-sha512密码。请参见下面的代码。
来源在GitHub上:https://github.com/badzong/node-verify-flask-security-passwords
var crypto = require('crypto');
var pbkdf2_sha512 = require('pbkdf2-sha512');
function b64trimmed(buf) {
return buf.toString('base64').replace(/=*$/, '').replace('+', '.');
}
function b64decode(str) {
// . in Base64?
str = str.replace('.', '+');
if (str.length % 4) {
str += '='.repeat(4 - str.length % 4);
}
return new Buffer(str, 'base64');
}
function get_hmac(secret, password) {
var hmac = crypto.createHmac('sha512', secret).update(password).digest('base64');
return hmac;
}
function get_hash(password, salt, rounds) {
// FIXME: KeyLenBytes is hardcoded
var h = b64trimmed(pbkdf2_sha512(password, salt, rounds, 64));
var joined_hash = ['', 'pbkdf2-sha512', rounds, b64trimmed(salt), h].join('$');
return joined_hash;
}
function verify_hash(password, stored_hash) {
var scheme = stored_hash.split('$')[1];
var rounds = stored_hash.split('$')[2];
var salt = stored_hash.split('$')[3];
// FIXME: Maybe throw an exception
if (scheme !== 'pbkdf2-sha512') {
return false;
}
var h = get_hash(password, b64decode(salt), rounds);
return h === stored_hash;
}
function new_hash(password, rounds) {
// FIXME: Salt size is hardcoded
var salt = crypto.randomBytes(16);
return get_hash(password, salt, rounds);
}
var password = 'Example Password';
// Usage:
var h = new_hash(password, 20000);
console.log('HASH ' + h);
console.log('VERIFY ' + verify_hash(password, h));
// Usage for passwords generated with flask_security:
// SECURITY_PASSWORD_SALT is set in config.py and used by flask-security
var SECURITY_PASSWORD_SALT = 'Many random bytes...';
var password_hmac = get_hmac(SECURITY_PASSWORD_SALT, password);
var h = new_hash(password_hmac, 20000);
console.log('HASH ' + h);
console.log('VERIFY ' + verify_hash(password_hmac, h));