Encryption

從 PBKDF2 獲取 32 字節的最佳方法

  • January 30, 2014

使用 PBKDF2 輸出作為 HMAC 密鑰,散列兩個不同的輸入 - 一次用於 20 字節,一次用於 12 :

using (var PBKDF2 = new Rfc2898DeriveBytes(passwordBytes, salt, 100000))
{
   HMACSHA1 hmac = new HMACSHA1(PBKDF2.GetBytes(20));
   hmac.Initialize();
   byte[] aesKey = hmac.ComputeHash(new byte[] { 1, 0, 1 })
       .Concat(hmac.ComputeHash(new byte[] { 1, 1, 1 })).Take(12).ToArray();
}

或者執行 PBKDF2 兩次,拆分迭代,並使用 2 種不同的鹽:

byte[] aes2;
using (var PBKDF2 = new Rfc2898DeriveBytes(passwordBytes, salt1, 50000))
   aes2 = PBKDF2.GetBytes(20);
using (var PBKDF2 = new Rfc2898DeriveBytes(passwordBytes, salt2, 50000))
   aes2 = aes2.Concat(PBKDF2.GetBytes(12)).ToArray();

參考資料:Rfc2898DeriveBytesHMACSHA1

稍微了解一下上下文會有所幫助。我假設您正在嘗試獲得基於密碼的密鑰,並且您正在嘗試最大化猜測密鑰所需的蠻力時間。但也許這些數據將用作標籤,或者您有興趣最大限度地利用時間來創建密碼密鑰字典或其他東西。

我會考慮攻擊者在做出決定時必須經過的搜尋空間。第一個有一個搜尋空間 $ |passwordBytes|\times|salt| $ . 第二個有一個搜尋空間 $ |passwordBytes|\times 2\times|salt| $ , 所以需要 $ O(2^{|salt|}) $ 更多的計算。將迭代次數加倍只會使計算加倍(即增加一點複雜性)。對於您的第二個選項,計算字典的時間會更長。

但是,實際上在第二種方案中只說前 20 個字節或只說最後 12 個字節會更容易(因為它使用較低的迭代計數),這可以更簡單地允許暴力破解另一半。為了防止這種情況,您最好遵循 CodesInChaos 的建議和級聯操作,但要確保最終輸出是來自安全原語的單個輸出。例如,您可以使用 $ tmp = PBKDF2(passwordBytes, salt1, 50000) $ 要得到 $ |passwordBytes| $ 數據,然後使用 $ SHA256(PBKDF2(tmp, salt2, 50000)) $ (甚至只是 $ SHA256(tmp || salt2) $ ) 得到 32 個字節。這使得搜尋空間盡可能大 $ |passwordBytes|\times 2\times|salt| $ 但不會僅從輸出的一半或另一半洩漏資訊。

無論如何,根據您使用數據的方式,我懷疑其他一些原語(如 SHA-256)可能對您有用。

有多種方法可以做到這一點,但我不推薦問題中的任何解決方案建議。

例如,您可以將 SHA-1 與 PBKDF2 一起使用,在 PBKDF2 之後使用 KBKDF,在 PBKDF2 之後使用經過身份驗證的加密/解密,從 PBKDF2 請求更長的輸出。根據您的需求,其中任何一種都可能是您的解決方案。有關詳細資訊,請繼續閱讀。

在 PBKDF2 之後使用 KBKDF 類似於您的建議雜湊兩次,但是“更好的密碼衛生”,如果進行密鑰派生,使用應該使用定義明確的密鑰派生操作。

同樣,從 PBKDF2 請求大於一個塊的輸出實際上類似於您建議執行 PBKDF2 兩次(因為它最終會做兩倍的工作)而不是使用 PBKDF2 和 HMAC-SHA2 導出 160 位值。

PBKDF2 簡介

PBKDF2 是一個基於 PRF(偽隨機函式)的函式。

PBKDF2 接受的偽隨機函式因實現而異。RFC #2898 指定了 HMAC-MD5 和 HMAC-SHA1。許多 PBKDF2 實現使用 HMA-SHA1,並且許多可用的測試向量都使用 SHA1(如 RFC 6070)。

但是,PBKDF2 不綁定到 HMAC-SHA1。較新版本的規範(例如NIST SP 800-132)允許基於任何 NIST 批准的雜湊(SHA-1 或 SHA-2 系列,例如 SHA-256 或 SHA-512)的任何 HMAC。

將 HMAC-SHA-1 與 PBKDF2 一起使用會為密碼的熵設置 160 位上限。如果你想保留高熵密碼的熵(幾十個隨機字元),那麼這將成為一個問題。因此,如果您需要具有全熵的 256 位機密,那麼您不得使用 SHA-1,而必須選擇 SHA-256。

解決方案

使用 PBKDF2 導出 256 位機密的解決方案在 NIST SP 800-132 中進行了相對簡單的解釋。

  1. 將 HMAC-SHA-256 與 PBKDF2 一起使用(可能需要不同的 PBKDF2 實現)。注意:如上所述,這將更好地保留高熵密碼的熵。
  2. 使用 PBKDF2 創建最多 160 位的機密,用於密鑰派生(例如 NIST SP 800-108、KBKDF)或密鑰包裝(例如 NIST SP 800-38F、AES-KW)以派生或解密 256-有點秘密。
  3. 使用 PBKDF2 算法允許比散列大小更大的輸出。因此,您可以使用 PBKDF2(使用 HMAC-SHA1)導出 256 位值(使用的時間是上面第 2 項的兩倍),並且不能提供更多安全性來抵禦密鑰暴力攻擊。

最重要的是要承認這些選擇中的每一個都會導致不同的密鑰。因此,出於互操作性的考慮,您可能受限於可以選擇的選項。

引用自:https://crypto.stackexchange.com/questions/13229