設置/更改密碼的密碼功能:我應該應用 bcrypt 伺服器端還是客戶端?
我正在編寫一個網頁,使用者可以在該網頁上設置(註冊時)和更改他/她的密碼。此頁面僅通過 HTTPS 提供。當使用者更改他/她的密碼時,他/她已經使用他/她的目前密碼進行了身份驗證。
我打算使用 bcrypt 來加密和加鹽密碼。這應該在客戶端(瀏覽器)還是在伺服器上完成?在客戶端的情況下,我可以在伺服器上驗證 bcrypt 應用了至少
X
(例如,12 次)迭代。
通常密碼散列是在伺服器端完成的。不需要,但是如果您使用客戶端密碼擴展,則需要注意一些事項。
- 您的網路客戶端需要啟用 javascript。人們可能出於安全、隱私或可訪問性的原因禁用它。或者因為noscript瀏覽更方便。或者因為他們想減少電池消耗。
- 資源限制 - 如果客戶端沒有高端電腦,則高級密碼散列可能需要比預期更長的時間。也許他們的 CPU 比台式機、筆記型電腦或伺服器慢得多。也許他們沒有太多可用的 RAM。(對於記憶體硬密碼雜湊算法,bcrypt 不是。)
- 攻擊者/防御者效率 - 如果可以選擇使用雜湊函式的本機優化實現或 JavaScript 中的客戶端實現來進行伺服器端雜湊,則伺服器端實現將更加高效。考慮使用相同參數在客戶端和伺服器端執行的算法。兩者都做相同數量的工作,但伺服器將首先完成。為了滿足使用者對響應性的需求,與伺服器端的成本參數相比,您將降低客戶端雜湊的成本參數。如果您的密碼數據庫確實遭到破壞,這會使離線密碼破解者的工作變得更容易。
- 如果您進行客戶端密碼散列,則任何嘗試登錄的人都需要知道鹽。如果攻擊者可以預期從伺服器竊取密碼散列,這將允許攻擊者對特定目標使用基於預計算的攻擊。
有些人還添加了“密碼雜湊是密碼等效的,因此客戶端雜湊根本不增加安全性。” 對於那些認為密碼散列是經過身份驗證的加密(它不是)的替代方案的人來說,這是一個很好的建議,但人們經常錯誤地將其用作不進行客戶端密碼拉伸的論據。這是一個不好的論點,因為在客戶端或伺服器端,如果您不使用加密,您仍然容易受到竊聽
客戶端散列的一個主要優點是它減輕了密碼從伺服器延伸的負擔。為了驗證密碼,伺服器需要擴展它收到的每個密碼送出。(忽略成功的暴力預防。)這可能被用於拒絕服務攻擊。
對於桌面應用程序,我可能會推薦客戶端散列。(使用固定伺服器密鑰進行端到端加密。)
如果您使用客戶端密碼拉伸,那麼您不應該在您的數據庫中儲存原始密碼雜湊。這將允許任何竊取密碼雜湊數據庫的人以任何使用者身份登錄,而無需確定他們的密碼是什麼。而是儲存散列的散列。就像在類似的東西 $ \text{SHA-512}(\text{bccrypt}(password, salt)) $ .
(Bcrypt 將在客戶端和 SHA-2 伺服器端完成。通常,密碼的普通散列是不安全的,但是散列散列是可以的,因為輸入已經被加鹽和拉伸。人們不會繞過bcrypt 部分並直接搜尋 SHA-2 原像,因為與猜測和散列密碼相比,查找原像會浪費時間。)
你說:
我可以在伺服器上驗證 bcrypt 應用了至少 X(例如,12)次迭代。
這讓我相信你誤解了一些東西。聽起來您想對客戶端和伺服器端都進行雜湊處理。
首先,除非您還擁有原始(明文)密碼,否則這是不可能的。其次,假設您正在測試,那是浪費精力 $ H(p) == H(p) $ 不是 $ H(H(p)) == \text{StoredHash} $ . (後者在客戶端和伺服器之間拆分雜湊拉伸工作。前者是多餘的,因為客戶端和伺服器都做同樣的工作。)
要驗證是否使用了足夠的 bcrypt 輪次,您只需對每個新密碼進行一次密碼散列(使用 bcrypt)。每當使用適當的參數更改帳戶密碼時,只需在伺服器端散列明文密碼即可。然後保存該雜湊以從那時起用於密碼驗證,以用於該密碼的剩餘生命週期。
最後,我認為我應該建議不要使用 client-side hashing。不是因為它本質上不好,而是因為我認為伺服器端散列會更安全、更容易實現。
您還應該使用argon2,它的設計成本很高,需要 CPU 和 RAM 資源。bcrypt 需要少量 RAM,它的成本參數僅用於更改 CPU 時間。argon2 是密碼雜湊競賽的獲勝者。
如果您使用 PHP,請考慮使用內置密碼雜湊 API,無論您使用 bcrypt 還是 argon2。它支持這兩種算法,為您處理鹽生成,並且是一個非常簡單的 API。