Aes

從較短的主密鑰派生 AES 密鑰和 HMAC 密鑰

  • April 20, 2016

我在 .NET 中工作,據我所知,密鑰派生的唯一選擇是 PBKDF2-HMAC-SHA1。SHA1 的輸出大小只有 160 位。但我正在實施經過身份驗證的加密,因此需要 512 位密鑰材料(一個 256 位 AES 密鑰和一個 256 位 HMAC 密鑰)。我最初的想法是在 PBKDF2 中輸入密碼、鹽和高 numberOfIterations 以導出 AES 密鑰和 HMAC 密鑰。

有幾個人指出,我讓攻擊者的工作變得更容易。從 PBKDF2-HMAC-SHA1 獲取 512 位密鑰材料需要 ceil(512/160) = 4 個呼叫 * numberOfIterations。然而,攻擊者只需要 AES 密鑰來解密消息,因此他/她只需要執行 ceil(256/160) = 2 個呼叫 * numberOfIterations。

我已閱讀有關如何解決此問題的兩條建議:

  1. 使用 PBKDF2-HMAC-SHA512。它將為兩個鍵提供足夠的輸出。不幸的是,.NET 似乎不支持這一點。
  2. 使用 PBKDF2-HMAC-SHA1 和密碼、鹽和高 numberOfIterations 輸出 160 位主密鑰。然後使用 HKDF-Expand 將主密鑰擴展為兩個 256 位密鑰。不幸的是,據我所知,.NET 沒有提供 HKDF-Expand。

我在其他堆棧交換文章中閱讀過,例如這篇文章這篇文章,可以通過執行以下操作從主密鑰 (MK) 派生兩個密鑰:

  1. 使用使用者提供的密碼、160 位 salt 和高 numberOfIterations 通過 PBKDF2-HMAC-SHA1 創建 160 位 MK。
  2. 計算 HMAC-SHA256(MK,“e”) -> aesKey
  3. 計算 HMAC-SHA256(MK,“a”) -> hmacKey

這些步驟是否會為 AES-encrypt-then-HMAC-authenticate 生成一對合適的密鑰?

  • 注意 1:我意識到 256 位 aesKey 和 256 位 hmacKey 每個都只有 160 位熵,但這似乎並不重要,因為可能的攻擊路徑是密碼,而不是密鑰。
  • 注 2:儘管 .NET 確實提供了 HMAC-SHA256、HMAC-SHA512 等,但除了 PBKDF2-HMAC-SHA1 之外,它不提供 PBKDF2-HMAC 的選擇。

這些步驟是否會為 AES-encrypt-then-HMAC-authenticate 生成一對合適的密鑰?

是的。那會很好。實際上,它幾乎HKDF-Expand。

但是,正如您所注意到的,通過從 160 位密鑰派生兩個 256 位密鑰,您的有效安全性將“僅”是 160 位,因為攻擊者可以暴力破解中間密鑰。實際上,這根本不是問題,但是如果您有嚴格的要求,例如某些法規,您會想要解決這個問題。

一種方法是使用 PBKDF2 導出 320 位(需要兩次迭代),然後從中導出兩個 256 位密鑰。


雨披在評論中提到的使用每隔一個字節的 512 位 PBKDF2 輸出的想法也可以,但在密鑰分離方面有一點弱點。如果最終密鑰之一——AES 或 MAC 密鑰(或只是其中一個字節)——以某種方式洩漏,攻擊者可以通過僅計算每個密碼的一個 PBKDF2 呼叫來在比預期更短的時間內尋找另一個。

同樣,這可能不是一個真正的問題,因為您希望將兩個密鑰保密,並且攻擊時間只有四倍。不過,這似乎有點不整潔,而使用 HMAC/HKDF 進行密鑰派生是一個簡單的解決方案。

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