到現在爲止,我一直在使用md5和sha1加密我的PHP登錄密碼,但由於這些算法現在被認爲已過時並且不再安全,我想要構建一個新的登錄系統PHP函數password_hash和password_verify。然而,有一件事我找不到解決這些功能的方法:爲了避免重放攻擊的安全性,僅僅爲每個密碼設置單獨的鹽是不夠的。因爲如果攻擊者以某種方式竊聽客戶端和服務器之間的通信,他可以將用戶名和已加密的密碼散列發送到服務器,就像原始客戶端一樣。所以我的解決方案一直是創建一個額外的「鹽」(我不知道是否有官方稱謂),只對一次登錄嘗試有效。因此,客戶端從服務器獲取兩種鹽(每個用戶帳戶總是相同的,每次用戶帳戶都是相同的),加密用戶輸入的密碼並將散列發送到服務器。然後服務器檢查這個散列(例如$ Hash == sha1($ HashFromDbWithFixedSalt。$ RandomHash))。然後創建一個新的$ RandomHash。因此,即使攻擊者模仿用戶的通信,他也無法獲得不允許的訪問權限。安全的PHP登錄對重播攻擊
新的PHP函數確實支持salt,但是我找不到一種方法來實現我的舊解決方案,因爲數據庫中的哈希將包含固定哈希(每個用戶帳戶不同),但不包含隨機哈希(僅適用於一次嘗試)。有沒有人有想法或者可能已經解決了這個問題?
編輯:
這是我用來做什麼的:
新用戶註冊:
- 請爲該用戶創建一個隨機鹽。
- 將md5($ password_in_cleartext + $ salt)和鹽本身保存到數據庫。
用戶想要登錄:
- 用戶發送他的用戶名與服務器
- 服務器從數據庫中查找他的鹽和創建,它在節省額外的隨機鹽$ _SESSION。它將這兩種鹽發送給用戶。
- 用戶在客戶端(通過JS)加密他的密碼,如下所示:sha1(md5($ password_in_cleartext + $ salt_from_the_db)+ $ random_salt)。他將這個散列發送給服務器。
- 服務器檢查sha1($ hash_from_the_db + $ random_salt)== $ hash_the_user_sent。如果不相等,則創建一個新的random_salt並將其發送給用戶(返回步驟3)。
最好的方法是SSL,就像@samlev說的! – MozzieMD
在客戶端上散列密碼不是加密。如果有的話,它可以減少安全性,因爲它減少了攻擊者可能的搜索空間。使用SSL來保護客戶端和服務器之間的通信(即*是*加密),然後使用諸如BCrypt之類的東西來散列它們的原始密碼。 – samlev
另一個注意事項:在bcrypt中,salt是哈希密碼*的一部分。我知道這聽起來不太安全,但事實並非如此。 – samlev