我有一个用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));
        

09-12 06:10