我有一个基本的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 :(得分: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(这是我常用的),它们公开了一个函数来直接将字符串与哈希值进行比较,就是这样。