如何正确比较加密的密码字符串?

时间:2016-12-06 18:01:07

标签: javascript node.js cryptojs

我有一个基本的html页面,其中包含用户名和密码输入框。随着登录按钮。我正在使用cryptojs来尝试比较加密字符串。

我相信我的问题是因为我随机生成了我的密钥和iv。你们对我能改变什么都有任何建议吗?

app.post('/authenticate',function(req,res){
conn.open(connString, function(err){
if(err) return console.log(err);

var loginID = req.body.LoginID,
    passWord = req.body.PassWord;

//-------------------------Security---------------------------
    // create random Word Arrays for key and Salt
    var key = CryptoJS.lib.WordArray.random(16);
    var iv  = CryptoJS.lib.WordArray.random(16);

    // Encrypt Password using key and Salt. Changes every time but will always decrypt to same password.
    var encrypted = CryptoJS.AES.encrypt(passWord, key, { iv: iv }).toString();
    var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv }).toString();

    console.log(decrypted);

//-------------------------END Security------------------------    

conn.query("SELECT PassWord from pub.User WHERE LoginID ='" + loginID  + "'",function(err,data){

    if(err) return console.log(err);   
    res.json(data);

    setValue(data);

    function setValue(value) {
    someVar = value;
    }
        for(key in someVar) {
            if(someVar.hasOwnProperty(key)) {
                var value = someVar[key];
                console.log(value.PassWord);
                console.log(encrypted);

                    if(value.PassWord == encrypted)
                    {
                        console.log("pass");
                    }
                    else
                    {
                        console.log("Fail");
                    }
            }
        }

        conn.close(function(){
        console.log('Login Complete');
        }); 
    }); // conn.query

}); //END conn.open(connString, function(err){
}); // END app.post('/authenticate'

谢谢,

2 个答案:

答案 0 :(得分:0)

你是对的。通过使用随机生成的密钥/ iv,您的encrypted密码字符串将始终不同,即使它decrypt为相同的值。因此,您将无法按照您的方式比较加密字符串。

我认为您应该问自己的第一个问题是,一旦将密码存储在数据库中,您真的需要能够解密密码吗?如果没有,您可能最好使用简单的哈希。你可以使用Node的内置Crypto包 - 这就是我通常用来存储散列密码的东西。我在Utils包中添加了一些实用方法,例如:

const crypto = require('crypto');

/**
 * hashPassword creates a password hash from the supplied password and
 * salt values.
 *
 * @param {string} password
 * @param {string} salt
 * @returns {string}
 */
function hashPassword(password, salt) {
    let seed = sha1Base64(password, salt);
    return sha256Hex(seed);
}

/**
 * sha1Base64 returns a signature using the supplied string and key.
 *
 * @param {string} str
 * @param {string} key
 * @returns {string}
 */
function sha1Base64(str, key) {
    return crypto.createHmac('sha1', key)
        .update(new Buffer(str, 'utf8'))
        .digest('base64');
}

/**
 * sha256Hex returns a string hash of the supplied data.
 *
 * @param {string|number|object} data
 * @returns {string}
 */
function sha256Hex(data) {
    return crypto.createHash('sha256')
        .update(data)
        .digest('hex');
}

hashPassword函数将创建一个64位字符的十六进制数字字符串。您可以了解哈希密码以将其存储在数据库中,然后在提交登录表单时对用户密码进行哈希处理。同样的事情,只有这不需要任何外部包。

但是,每次仍然需要使用相同的盐。您可以通过环境变量(更安全)分配系统范围的盐,在每个用户或每个帐户的基础上保留一个数据库(安全性较低),或者在一个配置文件中放置一个(可能是坏的)理念)。这实际上取决于你要保护的内容,以及你必须如何狂热 - 你是为个人博客创建登录区域还是为Chase Bank创建面向消费者的网站?只要确保你的盐足够长且随意。您可以使用函数生成任意长度的随机字符串:

/**
 * randomString returns a random alphanumeric string of the specified length.
 *
 * @param {number} [length]
 * @param {boolean} [special]
 * @returns {string}
 */
function randomString(length = 10, special = false) {
    let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    if (special) chars += '-_%!@#$^&*';
    let cLength = chars.length,
        sRandom = '';
    for (let i = 0; i < length; i++) {
        sRandom += chars[Math.floor(Math.random() * cLength)];
    }

    return sRandom;
}

对于我曾经做过的大多数事情,使用像这样的哈希就足够了。

希望这有帮助!

答案 1 :(得分:-1)

为什么选择Cryptojs?我认为有更好的选择,比如Bcrypt(这是我常用的),它们公开了一个函数来直接将字符串与哈希值进行比较,就是这样。

试一试:https://www.npmjs.com/package/bcrypt