2016-12-06 95 views
1

我有一个带有用户名和密码输入框的基本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' 

谢谢你,

+0

你应该使用类似bcrypt/pbkdf2/scrypt的东西来代替密码。 – mscdex

回答

0

为什么会选择Cryptojs?我想有更好的选择,像Bcrypt(这是我经常使用),它们公开的函数的字符串直接与比较哈希值,就是这样。

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

+0

那么我不完全确定什么是更好的使用。我发现更多的cryptojs比我最初加密,所以我坚持下去。感谢您的链接!我会试一试,看看这对我是否更好。 – AnthonyFastcar

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字符串。您可以得到散列密码的一般想法,将其存储在数据库中,然后在提交登录表单时散列用户的密码。这里同样的事情,只有这不需要任何外部包。

但是,您仍然需要每次都使用相同的盐。您可以通过环境变量(更安全)分配一个系统范围的salt,将数据库中的一个保留在每个用户或每个帐户的基础上(不太安全),或者将某个配置文件放在某处(可能是一个坏的理念)。这实际上取决于你想要保护的是什么,你必须是多么的狂热 - 你是否为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 += '-_%[email protected]#$^&*'; 
    let cLength = chars.length, 
     sRandom = ''; 
    for (let i = 0; i < length; i++) { 
     sRandom += chars[Math.floor(Math.random() * cLength)]; 
    } 

    return sRandom; 
} 

对于大多数我做过的东西,使用哈希像这样就足够了。

希望这会有所帮助!

+0

谢谢你的解释!它真的清除了我迷迷糊糊的一些东西。我今晚晚些时候会看到这个,所以我可以完全理解一切。再次感谢它真的帮助我。 – AnthonyFastcar