使用 BouncyCastle CCM 就地加密,IV 和 MAC 必須有多大?
我需要加密 20 個字節的數據,加密的 nonce + data + mac 大小不能超過 30 個字節。我有一個實現,但我不確定我是否在偷工減料並損害加密。
使用充氣城堡圖書館我能夠寫這個。
static (byte[],byte[]) encrypt(byte[] data, byte[] key, byte[] nonce) { var engine = new AesEngine(); var parm = new AeadParameters(new KeyParameter(key), 16, nonce); var chipher = new CcmBlockCipher(engine); chipher.Init(true, parm); var output = new byte[chipher.GetOutputSize(data.Length)]; var outputLength = chipher.ProcessBytes(data, 0, data.Length, output, 0); chipher.DoFinal(output, outputLength); return (output, chipher.GetMac()); }
這是我的想法。對於加密的數據,我知道以下資訊:
- 關於數據來源的元數據
- 數據加密的大致日期(直至當天)
有了這些資訊,我制定了一個隨機數,其中包含:
2 bytes meta + 8 bytes Unix ms timestamp
有了這個,我可以砍掉除了隨機數的最後 4 個字節之外的所有字節,因為這些是指示相關日期時間戳的最不重要的字節。
考慮到這一點,我可以將最終的完整編碼數據設為:
4 byte nonce + 20 byte encrypted + 2 byte MAC
這使它適合 30 字節的限制。
所以這是我的問題:
- 在這種情況下,16 位 MAC 是否有效?
- 從部分已知的數據中創建隨機數是否符合規定?
- 如何驗證我的 nonce 在程式碼中是否正確遞增?我只是似乎傳遞了一個靜態隨機數,即使它應該根據點擊率增加……對嗎?
所以我會按順序回答:
Q1:在這種情況下,16 位 MAC 是否有效?
您已經定義(部分)您的協議,但您還沒有定義您的系統。如果 MAC 不被接受怎麼辦?如果您只有 16 位 MAC,則 MAC 的值只有 65536 個。如果對手可以生成消息並將它們發射到接收器,那麼暴力強制標籤是完全可能的。即使你只能嘗試一次:有機會 $ 1 \over 65536 $ 被認為不夠安全。
使用 8 個字節是一個好主意,但是對於 nonce 來說只剩下 2 個字節,所以你只會有 65536 條消息。
Q2:從部分已知的數據中創建隨機數是否符合規定?
當然,Nonce 只需要是唯一的 - 但請注意,在 CTR 和 CCM 的情況下,nonce 大小也會影響可以創建多少計數器塊,因此每個 nonce 可以處理多少數據。從這個意義上說,CCM 就像 CTR。它甚至需要在計數器中增加一個字節的元資訊,從而為 nonce 和計數器留出更少的空間。
有點明顯,但另一個要求是接收器必須能夠重新生成隨機數。
Q3:如何驗證我的 nonce 是否在程式碼中正確遞增?我只是似乎傳遞了一個靜態隨機數,即使它應該根據點擊率增加……對嗎?
不,計數器正在遞增 - 而不是隨機數。隨機數僅用於創建計數器。通常,nonce 只是計數器中最重要的部分。在 CCM 的情況下也是如此,即使最高有效字節被跳過。例如,參見NIST SP 800-38C第 A.3 章,其中正在實施計數器增加。
在 GCM 模式下,也有可能對 nonce 進行預處理以生成初始計數器值,因此在經過身份驗證的加密的各種實現之間如何使用 nonce 肯定存在差異,儘管實際上所有這些都使用了 CTR 模式模式。
請注意,NIST 指定的計數器模式並沒有指定計數器值必須如何生成;實現可以自由選擇他們想要的任何方案。