使用 AES GCM 進行確定性加密 - 如何選擇 IV(隨機數)
我在密碼學方面沒有很大的背景,所以我希望這些問題不是很愚蠢。我不想重新發明輪子,我只是在尋找有關如何建構以下內容的最佳實踐的建議。
我已經尋找和閱讀了幾個小時,但沒有找到任何滿足我擔憂的答案。因此,我提出了一個解決方案,我希望得到一些回饋。
問題
我想為敏感資訊的確定性加密提供無狀態的微服務。其中一些資訊(即:個人辨識號)可能會用作數據庫中的主鍵,這就是密文需要確定性的原因。
該微服務將具有 oauth2 模式,因此它將是加密和解密的唯一點。根本不會有密鑰共享。
不同的應用程序將呼叫此服務來加密敏感資訊,在其他人之間共享它,並且在某些時候,另一個具有正確憑據的應用程序會要求對其進行解密。
API虛擬碼:
encrypt (sensitiveInfo: String): String decrypt (ciptherTextStruct: String): String
注意事項
- 使用 AES-GCM,IV 必須是唯一的
- IV 必須與密文一起返回
- IV 不應該是明文的散列,因為它們不提供機密性。
- 密文將在一個結構中返回(其中將包含一個用於密鑰輪換的密鑰“版本”)
建議的解決方案
基本上,我認為 IV 是另一個密文:
mail (input) +--> hash() --> IV \ +--> mail --> PlainText |-> Cipher text 1 (C1) password (secret) ---------> Key /
然後:
Cipher text 1 (C1) --> IV \ mail ----------------> PlainText |-> Cipher text 2 (C2) password (secret) --> Key /
最後,該方法
encrypt (sensitiveInfo: String): String
會返回一個C1+C2的結構體(可能是一個json結構體),該方法decrypt (ciptherTextStruct: String): String
會C1
從該結構體中取出,用作IV,C2
以及秘鑰,並按預期返回明文。回饋
我擔心在這張照片中沒有看到關於玩 C1 和 C2 的任何資訊披露。
**編輯:**我也可以使用第二個 IV 作為 的散列
C1
,這樣就不可能在 C1 和 C2 之間播放。我很確定我是在重新發明輪子,所以我非常感謝一些幫助,了解哪種方法是最好的。
謝謝!
您提出的解決方案大部分都會起作用。您唯一需要更改的是,在計算時使用不同的鍵 $ C1 $ 和 $ C2 $ . 兩個密鑰都可以從一個共同的主密鑰派生,但它們不能相同。
不過,您的解決方案有點複雜。將確定性 IV 計算為純文字的 MAC(以及附加數據,如果有的話)會容易得多。
把這些放在一起,我的建議是:
加密
輸入值: $ S $ (密碼), $ M $ (資訊)
$ MK = scrypt(password), K_1 = HKDF(MK, “IV Key”), K_2 = HKDF(MK, “Enc Key”) $
$ IV = MSB_{96}(HMAC(K_1, M)), C=ENC(K_2, IV, M) $
返回值: $ IV, C $
解密
輸入值: $ S $ (密碼), $ C $ , $ IV $
$ MK = scrypt(password), K = HKDF(MK, “Enc Key”) $
$ M = DEC(K, IV, C) $
返回值: $ M $