塊計數器大小引起的消息長度限制
維基百科報導了有關 ChaCha20 算法的以下資訊:
ChaCha20 的實現參考已在 RFC 7539 中發布。IETF 的實現修改了 Bernstein 發布的算法,將 64 位隨機數和 64 位塊計數器更改為 96 位隨機數和 32 位塊計數器
$$ 34 $$. 修改算法時名稱沒有更改,這可能是開發人員混淆的根源。由於減少了塊計數器,IETF 變體可以安全加密的最大消息長度為 2^(32)-1 個 64 字節的塊(約 256 GiB)。對於這還不夠的用途,例如文件或磁碟加密,RFC 7539 建議使用具有 64 位隨機數的原始算法。
我的問題是:
在這句話中
…可以安全加密的最大消息長度…是 2^(32)-1 個 64 字節的塊(約 256 GiB)
我對此有以下相關問題:
- 是否暗示重複使用相同的塊計數器是一種風險?
- 這個風險是怎麼計算的?風險的公式是什麼?
- 如果是重複塊計數器的問題,那麼塊大小不應該與隨機數相同嗎?96 位 = 12 字節?
- 如果不是重複塊計數器是風險的來源,那麼風險是否僅基於編碼數據的總長度?這種風險的公式是什麼?
從 RFC 可以看出,ChaCha20 塊的構造如下:
state = constants | key | counter | nonce
然後在多輪中對其進行處理。因此,在接下來的 Q/As 中,請記住這一點。
1. 是否暗示重複使用同一個塊計數器是有風險的?
是的。如果您使用 32 位計數器,則假定它以模組化方式使用,使用模 $ 2^{32} $ 計算。這意味著 $ \operatorname{inc}(2^{32} - 1) = 0 \mod 2^{32} $ . 即它溢出並重置為初始計數器 0。
這意味著狀態將獲得相同的值(其他組件都不會因相同的 nonce 而改變),這意味著密鑰流開始重複自身。否則狀態的處理是確定性的,因此您將獲得相同的密鑰流塊。
2. 該風險是如何計算的?風險的公式是什麼?
在下面的計算中 $ P_x $ 是一個明文消息塊, $ S_x $ 是通過使用 ChaCha20 輪處理狀態生成的密鑰流塊,並且 $ C_x $ 是密文的塊(其中最後一個塊可能是部分塊,具體取決於消息的大小)。 $ x $ 是塊在明文/密鑰流/密文中的位置。
這基本上是所謂的many-time-pad。如果您有兩個消息塊 $ P_0 $ 和 $ P_{2^{32}} $ 那麼你會有 $ C_0 = P_0 \oplus S_0 $ 和 $ C_{2^{32}} = P_{2^{32}} \oplus S_{2^{32}} $ . 但是因為 $ S_0 = S_{2^{32}} $ 你可以看到重寫為 $ C_{2^{32}} = P_{2^{32}} \oplus (C_0 \oplus P_0) $ 或者,經過一些重新排列 $ P_0 \oplus P_{2^{32}} = C_0 \oplus C_{2^{32}} $ ,即您通過對同一位置的密文進行異或運算,洩漏了消息的兩個明文塊的異或。
這種風險是 100%。洩露多少資訊取決於消息塊的內容。請注意,如果多次跨越相同的限制,則可以獲得更多資訊,因為您現在可以以成對的方式對多個塊進行異或。
3.如果是重複block counter的問題,那麼block size不應該和nonce一樣嗎?96 位 = 12 字節?
那不適合該州;ChaCha20 使用特定的狀態大小指定,其中狀態由 16 個 32 位字或 512 位組成。
4. 如果不是重複塊計數器是風險的來源,那麼風險是否僅基於編碼數據的總長度?這種風險的公式是什麼?
這是關於重複計數器,所以這個問題不適用。
請注意,正確的實現應該失敗而不是溢出。不幸的是,對於線上實現,明文消息的大小事先不知道,那將是在加密之後 $ 2^{32} $ 塊。