從密碼中獲取 IV 是否安全?
我遇到了一種使用 AES-256 加密文件的加密方案。您可以在下面看到解密常式的初始化:
salt = scrambled_file.read(16) key_and_iv = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, 50000, 48, OpenSSL::Digest::SHA512.new) key = key_and_iv.byteslice(0,32) iv = key_and_iv.byteslice(32,16) cipher= OpenSSL::Cipher::AES256.new(:CBC) cipher.decrypt cipher.key = key cipher.iv = iv decrypted_data = cipher.update(scrambled_file.read(...))
它基本上需要一個密碼和一個 16 字節的隨機鹽,然後通過 PBKDF2 (SHA512) 推送它。之後,密鑰取自前 32 個字節,IV 取自其後的 16 個字節。
從與密鑰相同的雜湊中派生 IV 是否安全?
是的。PBKDF2 派生一個 DK,即“派生密鑰”,與隨機無法區分。這主要是因為 PBKDF2 中的函式是 HMAC,而 HMAC 是 PRF。讓我們看看維基百科的定義:
在密碼學中,偽隨機函式族(縮寫為 PRF)是一組可高效計算的函式,它們以下列方式模擬隨機預言:沒有有效的算法可以區分(具有顯著優勢)從 PRF 族中隨機選擇的函式和隨機預言機(一個輸出完全隨機固定的函式)。
這也意味著派生密鑰的字節是獨立的,甚至是相互獨立的。這意味著只要使用來自輸出的單獨字節,我們就可以將 DK 值拆分為一個鍵和一個 IV。
現在,幸運的是,提供的方案使用 SHA-512 作為底層雜湊函式。這意味著如果我們需要 256 位密鑰材料和 128 位 IV 材料,則不需要執行額外的計算。
如果使用 SHA-256 雜湊,則 PBKDF2 函式將需要額外執行。不幸的是,在上述方案中,攻擊者不必執行這樣的額外執行。這是因為攻擊者只需驗證密鑰;它可以在找到密鑰時計算IV。因此,使用較小的散列函式需要合法使用者進行更多操作,而不會帶來任何安全優勢。這對於 PBKDF 來說是一個不好的屬性——不幸的是,PBKDF2 存在這種屬性。
因此,只要您的密鑰和 IV 保持在散列的輸出大小以下,上述方案就是安全的。
如果您需要的輸出比單個散列所需的多,則可以使用基於密鑰的密鑰派生函式 (KBKDF)(例如 HKDF)執行額外的計算。在這種情況下,一個好的方案是:
derivedKey = PBKDF2(password, salt) key = HKDF(derivedKey, "Key") iv = HKDF(derivedKey, "IV")
該方案是安全的並不意味著它是最優的。您可以考慮使用記憶體硬 PBKDF,例如 scrypt 或較新的 Argon2 變體之一,而不是 PBKDF2。您可能還會查看經過身份驗證的密碼(例如 GCM),以向您的密文添加完整性和真實性。
當然,該方案確實依賴於作為安全隨機值的鹽。請確保是這種情況,否則,您可能會得到一個重複的密鑰,IV 用於相同的密碼,從而破壞安全性。
PBKDF2 的大量迭代(“工作因素”)使得攻擊相對較弱的密碼變得更加困難(並且大多數密碼相對較弱)。