客戶端密碼散列是否可以進行伺服器端密碼強度驗證?
假設我希望在伺服器上設置經典的使用者名和密碼身份驗證策略。所有通信都通過 TLS 加密。但理想情況下,我仍然不希望伺服器能夠以純文字形式讀取密碼,即使是暫時的。為此,客戶端可以發送經過雜湊處理和加鹽的密碼(為簡單起見,我們假設它是使用者名)。我們稱之為派生密碼。然後,伺服器將依次使用 Bcrypt 或 PBKDF2 等算法對派生的密碼進行散列和加鹽,並將其儲存以供將來的請求使用。
到目前為止,這些都不是新奇的,並且有很多關於這個話題的討論。但是我在這些討論中找不到的是如何對有問題的純文字密碼的強度進行伺服器端驗證?可以繞過任何客戶端強度驗證,或者客戶端應用程序可能存在無法充分驗證強度的錯誤,因此,強度驗證應該在伺服器上完成。但同時我不希望伺服器訪問純文字密碼。
所以我的問題是,這兩個要求是互斥的,還是有什麼方法可以同時滿足這兩個要求?可以根據派生密碼進行強度驗證嗎?至少,是否可以使用派生密碼檢查純文字密碼的長度,以防止使用空密碼進行註冊?還是作為項目所有者,我是否只需要接受某些使用者可以繞過客戶端驗證並且如果他們的帳戶因繞過客戶端強度驗證而受到損害,則無需承擔任何責任?
我意識到可以採用混合策略,其中僅在註冊/密碼重置期間以純文字形式從客戶端發送密碼,並在任何後續請求中以加鹽、散列形式發送密碼。這是對一直以明文發送密碼的改進,但仍然不能滿足從不將明文密碼暴露給伺服器的要求。
您無法實際檢查發送給您時已經散列的任何密碼的強度。散列函式在設計上是單向函式,這意味著您不應該能夠反轉散列並獲得有關輸入的任何有意義的資訊。
但是,您可以相當容易地驗證密碼不屬於常見的弱密碼的簡短列表,例如空字元串“”、“abc”、“123”、“密碼”等。您只需通過用這些輸入伺服器端重複客戶端散列過程,並檢查是否相等。此類弱密碼列表的長度會受到性能限制。由於客戶端送出的雜湊是加鹽的,因此伺服器必須為每次註冊和密碼更改重新建構此列表。
因此,如果密碼僅作為散列值發送,則必須在客戶端執行大部分密碼完整性檢查。
正如您已經提到的,您對混合註冊方案的想法並不理想,其中密碼以純文字形式發送到伺服器以進行快速檢查。首先,通過讓客戶端發送純文字密碼而不是相同密碼的純雜湊值,您不會獲得太多收益。大多數受益於純文字密碼的完整性檢查都可以輕鬆地在客戶端執行。大部分伺服器端測試可能最好在常見弱密碼雜湊數據庫(彩虹表)中進行搜尋。
也就是說,在這樣的數據庫表中找不到散列,並不能保證密碼足夠強。如果您可以訪問純文字密碼,則可能很容易發現由字典中的三個或四個隨機單詞串聯而成的長密碼,但即使在相當大的彩虹表中也可能不是條目。