AES-CTR HMAC 串流 AEAD

本文件正式定義了以 AES-CTR HMAC 串流金鑰代表的數學函式 (以 proto 格式編碼為 type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey)。

這種加密方式大致採用的是 [HRRV15]1。如需安全性分析,請參閱 [HS20]2。另請注意,Tink 跨語言測試具備 aes_ctr_hmac_streaming_key_test.py 測試,其中包含 test_manually_created_test_vector,其中包含如何取得密文的完整逐步操作說明。

索引鍵和參數

索引鍵由以下部分描述 (本文件中的所有大小均以位元組為單位):

  • \(\mathrm{InitialKeyMaterial}\),位元組字串:初始金鑰內容。
  • \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
  • \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
  • \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).
  • \(\mathrm{HmacHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).
  • \(\mathrm{HmacTagSize} \in \mathbb{N}\).

有效鍵額外還滿足下列屬性:

  • \(\mathrm{len}(\mathrm{InitialKeyMaterial}) \geq \mathrm{DerivedKeySize}\).
  • 若 \(\mathrm{HmacHashType} = \mathrm{SHA1}\) 接著 \(\mathrm{HmacTagSize} \in \{10, \ldots, 20\}\),
  • 若 \(\mathrm{HmacHashType} = \mathrm{SHA256}\) 接著 \(\mathrm{HmacTagSize} \in \{10, \ldots, 32\}\),
  • 若 \(\mathrm{HmacHashType} = \mathrm{SHA512}\) 接著 \(\mathrm{HmacTagSize} \in \{10, \ldots, 64\}\),
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + \mathrm{HmacTagSize} + 8\) (這等於\(\mathrm{len}(\mathrm{Header}) + \mathrm{HmacTagSize}\) ,稍後會說明)。

如果金鑰不符合上述任何屬性,則 Tink 會拒絕金鑰 (剖析金鑰或建立對應的原始版本時)。

加密函式

如要加密具有關聯資料\(\mathrm{AssociatedData}\) \(\mathrm{Msg}\) 的訊息,我們會建立標頭、將訊息分成不同區隔、加密每個區隔,以及串連區隔。我們會在下列步驟中說明這些步驟。

建立標頭

如要建立標頭,我們首先會選擇 \(\mathrm{Salt}\)長度的統一隨機字串 \(\mathrm{DerivedKeySize}\)。接下來,我們選擇\(\mathrm{NoncePrefix}\) 長度為 7 的統一隨機字串

接著設定\(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\),其中標頭的長度會編碼為單位元組。請注意\(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\)。

接下來,我們使用 HKDF3 搭配雜湊函式 \(\mathrm{HkdfHashType}\),計算這則訊息中長度\(\mathrm{DerivedKeySize} + 32\) 的金鑰內容:\(k := \mathrm{HKDF}(\mathrm{InitialKeyMaterial}, \mathrm{Salt}, \mathrm{AssociatedData})\)。輸入內容會使用\(\mathrm{HKDF}\): \(\mathrm{InitialKeyMaterial}\) is \(\mathrm{ikm}\)的對應輸入內容中,\(\mathrm{Salt}\) 為鹽,\(\mathrm{AssociatedData}\) 則用於 \(\mathrm{info}\)。

字串 \(k\) 會分成兩個部分 \(k_1 \| k_2 := k\),例如\(\mathrm{len}(k_1) = \mathrm{DerivedKeySize}\) 和 \(\mathrm{len}(k_2) = 32\)。

正在分割訊息

訊息 \(M\) 分為多個部分: \(M = M_0 \| M_1 \| \cdots \| M_{n-1}\)。

為滿足以下條件:

  • \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{HmacTagSize}\}\).
  • 如果值為 \(n > 1\),則 \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{HmacTagSize}\}\)。
  • 如果為 \(n > 1\),則 \(M_{0}, \ldots, M_{n-2}\) 必須根據上述限制條件提供最大長度。

這項分割作業中 \(n\) 不得超過 \(2^{32}\)。否則加密會失敗。

加密區塊

如要加密區隔 \(M_i\),我們首先計算\(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b \| 0x00000000\),其中我們使用 Bigendian 編碼為 \(\mathrm{i}\) 4 個位元組進行編碼。如果為 $i < n-1$ 和 0x01,則將位元組 $b$ 設為 0x00

接著,我們會 \(M_i\) 使用 AES 點閱率金鑰 \(k_1\)和初始化向量\(\mathrm{IV}_i\)加密。換句話說,AES 叫用的輸入內容都是\(\mathrm{IV}_i, \mathrm{IV}_i + 1, \mathrm{IV}_i + 2, \ldots\),其中 \(\mathrm{IV}_i\) 會解讀為大端序整數。這樣做會產生 \(C'_i\)。

我們會使用 HMAC 和 \(\mathrm{HmacHashType}\) 透過 \(k_2\) 串連\(\mathrm{IV}_i \| C'_i\)提供的雜湊函式,計算標記。

接著,我們會串連密文和標記,以便取得 \(C_i\)。

串連區隔

最後,所有片段都會串連為\(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\),也就是最終密文。

解密函式

解密作業只會反轉加密。我們會使用標頭取得 Nonce,接著個別解密密文的每個區段。

API 可能會 (通常確實會) 允許隨機存取或存取檔案開頭,而不會檢查檔案結尾。這是刻意設定,因為可以從 \(C_i\)解密, \(M_i\) 不會解密所有先前和其餘的密文區塊。

不過,API 應小心謹慎,不要讓使用者混淆檔案結尾和解密錯誤:在這兩種情況下,API 都可能必須傳回錯誤,而忽略差異可能會導致攻擊者能夠有效截斷檔案。

金鑰的序列化與剖析

如要以「Tink Proto」格式序列化金鑰,首先要以顯而易見的方式將參數對應至 aes_ctr_hmac_streaming.proto 提供的 proto。version 欄位必須設為 0。接著,我們使用一般的 proto 序列化程序將上述內容序列化,然後將產生的字串嵌入 KeyData proto 的欄位值。我們將 type_url 欄位設為 type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey。接著將 key_material_type 設為 SYMMETRIC,並將這個項目嵌入一組金鑰組。我們通常會將 output_prefix_type 設為 RAW。不過,如果金鑰是以針對 output_prefix_type 設定的不同值剖析,Tink 可能會寫入 RAW 或先前的值。

如要剖析金鑰,我們會反向操作上述程序 (剖析原型時的方式)。系統會忽略 key_material_type 欄位。output_prefix_type 的值可以遭到忽略,或是拒絕 output_prefix_typeRAW 不同的鍵。如果金鑰的 version 與 0 不同,就會遭到拒絕。

參考資料


  1. [HRRV15] Hoang、Reyhanitabar、Rogaway、Vizar線上驗證加密機制及 Nonce 防濫用政策。CRYPTO 2015。 https://eprint.iacr.org/2015/189 

  2. [HS20] Google Tink 程式庫中的串流加密安全性。Hoang, Shen,2020 年。https://eprint.iacr.org/2020/1019 

  3. [HKDF] HMAC 式擷取並擴展金鑰衍生函式 (HKDF),RFC 5869。https://www.rfc-editor.org/rfc/rfc5869