我懷疑你會遇到的第一個問題(它是一個很大的問題)是你的數據庫沒有密碼哈希函數。當然,它可能具有MD5()和SHA1(),但是這些都是加密哈希函數。它有bcrypt()或scrypt()或PBKDF2()嗎?
使用加密哈希函數而不是密碼哈希函數意味着LinkedIn密碼可能被破解得這麼快。如果你沒有使用上述函數之一,那麼如果你的哈希被泄漏了,你將同樣容易受到攻擊。
你打算在回答你的問題假設你的數據庫確實支持密碼散列算法(使用bcrypt,只是因爲我要挑一個)。兩個備選方案:
哈希數據庫:
$db->query("SELECT COUNT(*) FROM users WHERE username = '?' AND password = BCRYPT(?, (SELECT salt FROM user WHERE username = '?'))", $username, $password, $username);
if($row['count'] != 1)
{
// Not authenticated. Throw exception.
}
在這種情況下,原始密碼發送到數據庫和一個簡單的是或否(0或1)被返回。這個數據庫通信可以被加密。散列和鹽從不保存在應用程序中。
哈希中的應用:
$db->query("SELECT username, salt, password FROM users WHERE username = '?', $username);
if(bcrypt($password, $row['salt']) != $row['password'])
{
// Not authenticated. Throw exception.
}
在這種情況下,哈希和鹽從數據庫到應用程序和原始密碼的散列拉和比較有完成。與數據庫的通信仍然可以加密。原始密碼永遠不會保存在數據庫內存中。
爲了提高效率,我們可以假設兩種哈希算法都是用C(或某種編譯語言)編寫的,並且可能由OS提供,因此需要花費相同的時間。應用程序散列選項可通過線路接收更多數據,而數據庫散列選項可發送更多數據並具有更復雜的查詢(實質上是兩個查詢,一個用於獲取salt,另一個用於實現比較)。可能無法按照我編寫該查詢的方式使用索引,但查詢可能會被重寫。由於兩種情況下的數據大小仍然可能是一個TCP數據包,因此速度差異可以忽略不計。由於子查詢,我將這稱爲應用程序哈希選項的勝利。
曝光。我會認爲原始密碼比哈希和鹽更敏感。因此,限制原始密碼的暴露似乎更安全,使應用程序散列最佳做法。
我想我簡化了這個例子,但你仍然可以在數據庫中嵌入加密方法,例如在sql server中使用clr對象 – Blootac
@Blootac好點。我已經爲實際的問題添加了一個答案,假設您的數據庫具有適當的哈希算法。 – Ladadadada
謝謝,正反兩方面的說明很好。 – Blootac