2016-12-06 50 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