如果在 AES-CTR 中增加 MAX 計數器會發生什麼?
ffffffffffffffffffffffffffffffff
假設您在 AES-CTR 中使用 IV/counter = 。如果你加密下一個塊,從而將計數器加一,會發生什麼?它會導致各種溢出錯誤嗎?
在 AES-CTR 中,“IV”和“計數器”是不同的概念。要加密消息,您需要指定一個隨機數,例如消息序列號——有時稱為“IV”。隨機數通常是 64 或 96 位,但它的長度可以是 0 到 128 位。為了安全起見,您絕不能重複使用帶有密鑰的隨機數。您正在使用的特定 AES-CTR 系統的隨機數長度決定了最大消息長度:在AES-CTR 內部,128 位字元串的一部分在用隨機數填充後的剩餘部分用於計算塊**內的塊資訊。
因此,例如,如果您發送消息 $ m_1 \mathbin| m_2 \mathbin| m_3 $ ,然後是消息 $ m’_1 \mathbin| m’_2 $ ,您可以在您的協議中為第一條消息選擇 nonce 42,為第二條消息選擇 nonce 69,密文將在內部計算為:
$$ \begin{align} c &= \bigl(m_1 \oplus \operatorname{AES}_k(42 \mathbin| 0)) \mathbin| (m_2 \oplus \operatorname{AES}_k(42 \mathbin| 1) \mathbin| (m_3 \oplus \operatorname{AES}_k(42 \mathbin| 2)\bigr), \ c’ &= \bigl(m’_1 \oplus \operatorname{AES}_k(69 \mathbin| 0)) \mathbin| (m’_2 \oplus \operatorname{AES}_k(69 \mathbin| 1)\bigr). \end{align} $$
(這裡 $ m_i $ 和 $ m’_i $ 每個正好是 128 位;塊計數器 0、1、2、……是在AES-CTR 內部維護的。)
對於(比如說)具有 96 位隨機數的 AES-CTR,最大消息長度為 $ 2^{32} $ 128 位塊,或 $ 2^{36} $ 字節。如果您嘗試加密一個 $ (2^{36} + 1) $ -字節消息?在那種情況下根本沒有定義它——比如除以零。 你應該避免設計一個甚至可能出現這個問題的協議;一個實現可能會做的事情可能會有所不同:它可以默默地環繞,有效地使用兩次填充加密消息;它可能會大聲失敗併中止計算;它可以讓惡魔從你的鼻子裡飛出來。
如果您使用 0 位隨機數怎麼辦,這樣最大消息長度為 $ 2^{128} $ 128 位塊,或 $ 2^{132} $ 字節?你沒有那麼多字節,也沒有足夠的時間等待世界上所有的電腦加密那麼多字節。
如果——除了內部塊計數器——你使用 64 位消息序列號作為隨機數怎麼辦?你會擔心繞圈嗎?提示:您正在按順序執行此操作。假設您需要一納秒來加密每條消息。您需要等待多少個世紀才能讓 64 位消息計數器溢出?
您預計會產生什麼溢出錯誤?AES 函式當然不知道您構造 16 字節明文塊的方式。
AES-CTR 通常使用 64 位 nonce 和 64 位計數器完成,因此它會更快溢出,之後 $ 2^{64} - 1 $ . 計數器值將環繞,或引發錯誤/拋出異常,或將變為 $ 2^{64} $ 接著 $ 2^{64} + 1 $ ,取決於您使用的程式語言(有時,取決於您是在調試還是發布模式下編譯!)。
對於 C 無符號整數類型
uint64_t
,如壞的)。Java plain 沒有無符號的 64 位整數,只有有符號的整數,但語言規範說明了它們在溢出時會發生什麼。
Python 只有大整數(沒有固定大小的整數,除了作為類型化數組的一部分),所以它很高興是一個 65 位的值(或 6,500 位的值)。
請查閱您的程式語言參考手冊(如果是彙編程式,請查閱 CPU ISA 手冊)。
根據您的身份驗證方案或 AEAD,您不想等待該計數器迴繞,因為您應該更早地重新輸入密鑰。例如,出於某種原因,AES-GCM 應該使用 96 位隨機數和 32 位計數器。