拆分雙重角色的密碼
我想提示使用者輸入一個密碼片語,以便通過一個密碼輸入與單獨的、通常(但不總是)互補的系統建立信任。
我本質上是在尋找一個密碼輸入和兩個密碼離開的框,其中保持最大熵,並且最小化攻擊者使用任一輸出密碼推導另一個密碼的能力。
有一些限制:
- 算法必須是公共知識。
- 不能涉及其他密鑰。
- 對於任何給定的輸入密碼,輸出密碼必須是確定的。
一個簡單的答案似乎是:
- $ \rm pass1 = HMAC(password, \text{ “Magic One”}) $
- $ \rm pass2 = HMAC(password, \text{ “Magic Two”}) $
使用這種方法,對於知道的人來說應該一樣困難 $ \rm pass1 $ 推導 $ \rm pass2 $ 就像他們猜測的那樣 $ \rm password $ .
有沒有更好的現有算法?我能找到的唯一參考資料是 Steve Bellovin 的Hashed Password Exchange Internet-Draft使用相同的基本方法。
具體來說,實際上是否有可能增加具有知識的人的難度? $ \rm pass1 $ 推導 $ \rm pass2 $ 超過猜測的難度 $ \rm password $ 本身,即使它需要花費部分可用的 $ \rm password $ 熵?
例如,讓我們假設 $ \rm pass2 $ 暴露在被“離線”攻擊的環境中,而 $ \rm pass1 $ 不那麼脆弱。在這種情況下, $ \rm pass1 $ 實際上也暴露在“離線”風險中 $ \rm pass2 $ .
你想要一對功能 $ (f_1,f_2) $ 從一組 $ S $ 密鑰集的可能密碼片語 $ K $ , 那是 $ f_1,f_2: S \rightarrow K $ . 這些函式是公開的,因為它們可以由任何人計算。
您的安全目標是發現成本 $ f_2(pw) $ , 知道 $ f_1(pw) $ , 應該大致和找到一樣昂貴 $ f_2(pw) $ 通過搜尋 $ pw $ , 使用 $ f_1(pw) $ 確認一個正確的猜測,然後簡單地計算 $ f_2(pw) $ .
在這種情況下,使用合理的 KDF 是您所希望的最好的。你計算一個長的位串 $ s = \mathit{KDF}(pw) $ . 字元串分成兩部分, $ s = s_1 || s_2 $ , 和 $ f_1(pw) = s_1 $ , $ f_2(pw) = s_2 $ .
這很好,因為: 在合理的假設下(KDF 看起來像一個隨機函式)。如果 KDF 看起來像一個隨機函式,那麼除非您知道函式的輸入,否則您不能使用函式值的一部分來說明函式值的任何其他部分。
它無法改進,因為: $ f_1(pw) $ 應該包含盡可能多的熵 $ pw $ 表示函式值 $ f_1(pw) $ 或多或少唯一確定 $ pw $ ,這意味著詳盡的搜尋將起作用。
對提議的解決方案的瑣碎評論:我們可以說 $ f_i = \mathit{KDF}(pw, i) $ ,與您的 HMAC 建議一致,但在實踐中,試圖確認猜測的人的工作量是合法使用者的一半。有了上面的提議,工作量是相等的。
要回答您的字面問題:
“具體來說,實際上是否有可能增加具有知識的人的難度? $ \rm pass1 $ 推導 $ \rm pass2 $ 超過猜測的難度 $ \rm password $ 本身,即使它需要花費部分可用的 $ \rm password $ 熵?”
答案是不”。
要了解原因,請注意,如果攻擊者知道(或可以正確猜測)原始主密碼,他們將能夠計算所有派生密碼。因此,猜測主密碼的能力意味著推導出所有其他密碼的能力。
但是,您可以做的是使每個派生密碼獨立於主密碼的某些部分,這將使攻擊者無法完全確認他們是否正確猜測了主密碼一個派生密碼。但是,如果主密碼旨在讓人記憶,我強烈建議不要這樣做,因為它會減少每個派生密碼的熵。
實際上,可以說最好的方法是首先將每個派生密碼選擇為適當長的隨機單詞序列,然後讓主密碼簡單地成為“派生”密碼的串聯。雖然這可以實現您的目標,並且如果派生密碼的數量不是太多的話可能是實用的,但它也會使整個方案變得微不足道且毫無意義,因為使用者可以直接輕鬆地記住派生密碼。
相反,為了實際使用,我建議使用合適的 KDF 從整個主密碼中派生出每個派生密碼,並接受猜測主密碼會危及系統的事實。如果這是不可接受的,最好的替代解決方案是簡單地使用兩個獨立的密碼。