本方案的安全性
我正在開發一個軟體,但我不確定它是否完全安全。
我有 22 Mb 的數據要加密多次使用,
隨機 IV(使用 OpenSSL lib 中的 RAND_bytes 生成)
和密碼 $ key = SHA3_{256}(PBKDF2(salt, password, 256000, SHA2-256)) $ .
來自 Qt
QCryptographicHash
、PBKDF2 和SHA_256
OpenSSL 的 SHA3_256,salt 也是由RAND_BYTE
256 位長生成的。現在我想知道你的意見,如果這個方案是安全的:
XOR 鍵和 IV 一起:
$$ encryptionKey = IV \oplus key\ $$ 加密 IV:
$$ firstBlock=E_{AES-EBC-256}(key, IV) $$ 加密數據:
$$ secondBlock = E_{AES-GCM-256}(encryptionKey, IV, data) $$ 接著:
$$ output << firstBlock\ output << secondBlock $$ 我不太確定這部分 $ E_{AES-GCM-256}(IV \oplus key, IV, data) $ .
我非常感謝您對此的看法。
回答完整的問題相當困難,但我會盡力回答。
您嘗試使用 IV 導出數據加密密鑰,因為您認為 IV 可能被過度使用。
NIST SP 800-38D 第 8.3 節狀態(對於不重複的機率 $ 2^{-32} $ ):
認證加密函式的總呼叫次數不得超過 $ 2^{32} $ ,包括所有 IV 長度和具有給定密鑰的經過身份驗證的加密函式的所有實例。
太好了,所以除非你呼叫 GCM 超過 40 億次(短期),那麼你應該沒問題,你可能不需要任何特殊的構造。
假設您不想限制 GCM 呼叫的數量。在這種情況下,您為每個加密派生一個密鑰。您可以使用基於密鑰的密鑰派生函式或 KBKDF。您可以使用的最好的可能是 HKDF。HKDF 也接受鹽,並且能夠根據需要從輸入中生成盡可能多的位。因此,您可以使用以下構造:
- $ salt = random() $
- $ seed = PBKDF2(salt, password, 256000, SHA2-256) $
- $ key = HKDF(seed, \text{“key”}) $
- $ iv = HKDF(seed, \text{“iv”}) $
- $ (ct, tag) = E_{AES-GCM-256}(key, iv, data) $
- $ output = encode(salt, (ct, tag)) $
現在說您不想為每個文件執行那些 256000 次迭代,並且您想一次加密/解密多個文件,那麼您可以執行以下操作:
- $ salt = random() $
- $ seed = PBKDF2(salt, password, 256000, SHA2-256) $
- $ salt_2 = random() $
- $ key = HKDF(seed, salt_2, \text{“key”}) $
- $ iv = HKDF(seed, salt_2, \text{“iv”}) $
- $ (ct, tag) = E_{AES-GCM-256}(key, iv, data) $
- $ output = encode(salt, salt_2, (ct, tag)) $
因為 HKDF 也可以使用鹽。對於每個文件,重複步驟 3 到 6。
一個技巧是只使用 HKDF-expand 並為密鑰和IV 生成 512 位。如果 HKDF 不可用,也可以使用其他更簡單的 KDF,例如 KDF1 或 KDF2。
至於你的方案,我看到了一些缺點。
- 對 SHA-3 的額外呼叫是虛假的;
- GCM 的 IV 最好設置為 96 位(12 字節),但 IV 的 XOR 和加密似乎建議使用 128 位的 IV;
- 密鑰和 IV 的 XOR’ing 不是安全密鑰派生函式;
- 密鑰長度現在被限制在 IV 的大小或引入額外的複雜性;
- 不建議為不同的相關算法重用派生密鑰。
這裡3和5的組合是最大的問題;您必須證明不安全的密鑰派生不會妨礙 GCM 算法的安全性。這不是你應該想做的事情。
與往常一樣,建議使用現有的協議和庫;有很多安全的可用。