如何從一個密碼中生成兩個不同的密鑰?
我正在設計一個系統,其中密碼既用於登錄也用於加密某些有效負載。
為了加密有效載荷,我從密碼中派生出一個密鑰。到目前為止非常簡單。
由於該加密應該是端到端的,因此密碼不會發送到伺服器,而是先進行雜湊處理,然後再發送到伺服器。然後,伺服器重新散列該密碼以將其儲存在數據庫中(出於與散列密碼相同的原因)。
最重要的是伺服器不能重建密碼而不是用於加密有效負載的密碼派生密鑰。
所以,我的問題是為每個實例選擇哪些算法。
我很確定要對密碼進行雜湊處理以進行身份驗證,我想使用 Scrypt。我知道它的測試時間還不夠長,但它似乎提供了最好的安全性。
為了從密碼中獲取密鑰,我的計劃是使用 PBKDF2。讀到它,有些人確實建議使用 Scrypt 而不是 PBKDF2,因為它對 GPU 攻擊更具彈性。我這樣做的問題是,如果我將 Scrypt 用於身份驗證和密鑰派生,我可能會將密鑰暴露給伺服器(在身份驗證期間)。
除了使用兩種不同的算法之外,我應該如何解決這個問題?
作為記錄,我使用 AES 進行加密,特別是 AES/GCM/NoPadding,儘管這不是一成不變的。
我的實現是用 Java 完成的,目前我正在使用 Bouncy Castle。
我這樣做的問題是,如果我將 Scrypt 用於身份驗證和密鑰派生,我可能會將密鑰暴露給伺服器(在身份驗證期間)。
如果您使用兩個雜湊,那麼一個失敗會破壞整個系統。使用一個比使用兩個減少損壞的機會。
我很確定要對密碼進行雜湊處理以進行身份驗證,我想使用 Scrypt。
Scrypt 不是雜湊,它是 PBKDF。PBKDF2 也是一個 PBKDF,而不是散列。
除了使用兩種不同的算法之外,我應該如何解決這個問題?
首先,不要使用兩個不同的 PBKDF。然後,您有兩種不同的攻擊向量,並且每個 PBKDF 花費的時間少於使用一個強大的 PBKDF 的時間。
您應該首先使用一些 PBKDF 派生主密鑰(我會推薦 Argon2,確保使用強設置並使用鹽)。派生主密鑰後,您應該使用 KDF(密鑰派生函式)來完全按照您的要求進行操作:從一個密鑰中生成兩個密鑰。然後你有 K1 和 K2。K1 可用於加密,K2 可以發送到伺服器,伺服器也應該對其進行雜湊處理(PBKDF 在那裡沒用)。
您還應該考慮伺服器是否應該儲存鹽(+硬碟故障後您可以訪問您的數據;-伺服器可以嘗試破解您的密碼)。