Encryption

AES-GCM 具有不同的 IV,但足夠接近計數器以導致重複

  • July 8, 2022

我打算使用 AES-GCM 或 AES-CTR 進行加密。但是,我從多個來源了解到,對於每條加密的資訊,IV 都必須是唯一的。不過我有一個疑問,如果我為兩個加密呼叫選擇不同的 IV 會怎樣,但是計數器加法會使 IV+計數器值對於某些塊相同。這會帶來安全風險嗎?

counter = 1, 2, 3, 4, 5, ...
iv1 = 100
iv2 = 102

// blocks of text1
b11 => (101 = 100 + 1), b12 (102 = 100 + 2), b13 (103 = 100 + 3), ...

// blocks of text2, notice that iv+counter is same as the block b13
b21 => (103 = 102 + 1), ...

但是,我從多個來源了解到,對於每條加密的資訊,IV 都必須是唯一的。

是的,這基本上是正確的。不過,術語有點錯誤:計數器塊必須是唯一的,因為計數器塊用作加密原語的輸入(例如 AES 塊密碼,將在本答案的其餘部分假設)。這反過來創建了一個密鑰流,並且密鑰流塊應該彼此獨立。然後將密鑰流與明文異或以形成密文。

不過我有一個疑問,如果我為兩個加密呼叫選擇不同的 IV 會怎樣,但是計數器加法會使 IV+計數器值對於某些塊相同。

通常,計數器塊是通過連接隨機數和實際計數器來創建的,每個塊都增加。計數器通常初始化為零。然後使用模加 1 增加計數器部分。它取決於每個實現,但通常實現要求您在開始時指定完整的 128 位計數器塊(“IV”),然後執行模添加。2128 $ 2^{128} $

當足夠多的塊被加密以致計數器塊中的計數器溢出到隨機數中時,就會出現問題。如果構造中的計數器是 32 位,那麼這發生在塊之後,即 64 GiB 的明文/密文,假設您從零開始計數器。232 $ 2^{32} $

這是一個使用十六進制的範例,假設一個大端計數器。選項 1在所有位/字節加法,選項 2在最後 32 位/字節上塊中的所有值都使用十六進制顯示。這是針對單個消息的,因此隨機數顯示為(隨機)靜態值。2128 $ 2^{128} $ 232 $ 2^{32} $

Counter block 0
--------------------------|---------
         Nonce           | Counter
8A73A31F2A33C13B5AE5234A  | 00000000

Counter block 1
--------------------------|---------
         Nonce           | Counter
8A73A31F2A33C13B5AE5234A  | 00000001

Counter block 2^32 - 1
--------------------------|---------
         Nonce           | Counter
8A73A31F2A33C13B5AE5234A  | FFFFFFFF

Option 1: Overflow into nonce (possible collision)

Counter block 2^32 
--------------------------|---------
         Nonce           | Counter
8A73A31F2A33C13B5AE5234B  | 00000000

Option 2: Wrap around of counter (collision with counter block zero of the same message)

Counter block 2^32
--------------------------|---------
         Nonce           | Counter
8A73A31F2A33C13B5AE5234A  | 00000000

所以通常加密應該在一定數量的塊被加密後停止。可以加密多少取決於計數器塊內計數器的大小。這就是為什麼大多數實現會使用模加 1 ,因為這意味著使用者可以控制 nonce 的大小,從而控制計數器;隨機數大小決定了可以加密的消息數量,而計數器大小決定了這些消息的大小。2128 $ 2^{128} $

這會帶來安全風險嗎?

是的,因為您現在可以對具有相同計數器塊和密鑰的密文塊進行異或運算。這意味著密鑰流是相同的。如果將密文塊異或在一起,則密鑰流將無效,最終得到兩個明文塊的異或。如果你有關於其中一個明文塊的資訊,那麼這立即意味著你也有關於另一個塊的資訊。

如果您想知道如何攻擊這樣的結構,請查看圍繞多次填充的範例或實踐。


現在對於 GCM:GCM 不接受計數器塊作為“IV”。相反,它假設 IV 是 96 位的隨機數。如果 IV 是任何其他大小,那麼它將使用該值來計算 nonce(或者如果未實現此功能,它將失敗)。它在 32 位的計數器塊中具有計數器的靜態大小。但是,它會跳過計數器值 0 並使用計數器值 1 來計算身份驗證標籤。這意味著它在個塊後溢出,因此 64 GiB - 32 個字節。232−2 $ 2^{32} - 2 $


筆記:

  • 原則上,計數器塊的配置完全取決於 CTR 模式的使用者;
  • 計數器如何通過實現增加也是如此,大端加法模2128 $ 2^{128} $ 非常常見,但那裡甚至很少有小端實現;
  • 由於生日問題,如果隨機數本身是隨機的,計數器塊內的小隨機數很快就會成為問題;
  • 強烈建議對 GCM 簡單地使用 96 位/12 字節隨機數;
  • 我們通常可以假設攻擊者知道計數器塊的內容,因此他們應該能夠輕鬆找到相同的密鑰流塊將它們異或在一起;
  • 一些使用者將整個 IV / 計數器塊隨機化為 CTR,這基本上意味著不知道計數器何時溢出 - 我不建議這樣做。

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