Encryption

實現 PBKDF2 + AES CBC + HMAC 的正確方法是什麼?

  • July 12, 2017

我一直在閱讀大量有關使用 HMAC 身份驗證實現 AES CBC 模式的正確方法。我已經看到了很多解釋,但是,我很難在包括密鑰推導、加密和解密在內的所有步驟上找到一個實際的真實範例(帶有程式碼)。我的應用程序使用 PBKDF2 進行密鑰派生。這是我到目前為止所擁有的:

派生密鑰

  1. 使用 KDF 生成 256 位“密鑰材料”
key_material = pbkdf2(user_password, salt, iterations, size:256, alg:sha256)
  1. 將密鑰材料分成兩半,生成用於加密和簽名的 x2 128 位密鑰
enc_key = key_material.split(0, 127)
mac_key = key_material.split(128, 255)

加密

  1. 生成 128 位初始化向量
iv = secureRandomBits(128)
  1. 做AES加密
cipher = aesEncrypt(plaintext, iv, mode:cbc, key:enc_key)
  1. 使用級聯 IV 和密碼位計算 MAC
mac = hmac(iv + cipher, alg:sha256, key:mac_key)
  1. 將結果值儲存到伺服器(被認為是不安全的儲存)
storeValuesToServer(cipher, iv, mac)

解密

  1. 從儲存中獲取數據
cipher, iv, mac = getValuesFromServer()
  1. 重新計算mac
new_mac = hmac(iv + cipher, alg:sha256, key:mac_key)
  1. 比較 Mac
if(mac != new_mac)
 throw 'Failed MAC check!'
  1. 做AES解密
plaintext = aesDecrypt(cipher, iv, mode:cbc, key:enc_key)

問題

這看起來正確嗎?這裡主要擔心的是:

  • 我是否正確導出了密鑰,根據 KDF 的輸出將它們分成兩半?
  • 我是否通過組合正確計算 HMAC iv + cipher。如果我這樣做了,這有關係cipher + iv嗎?

你會發現關於這個主題有很多分歧,尤其是密鑰推導。但是,是的,您的虛擬碼很好,儘管您可能想要修改 (0, 128) => (0, 127) 和 (129, 256) => (128, 255) …(如果我錯了,請糾正我?)。此外,您可能希望實現一個恆定時間比較函式來驗證 mac。

我是否正確導出了密鑰,根據 KDF 的輸出將它們分成兩半?

這可以。有些人會不同意。有關更深入的討論,參見此處此處。

我是否通過組合 iv + cipher 正確計算 HMAC。如果我做了 cipher + iv 有關係嗎?

是的,您正在正確計算 HMAC。不,cipher + iv 的順序根本不重要。如果您可以使用它,您可能需要考慮像GCM這樣的模式,它使用單個密鑰為您處理加密和身份驗證。

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