背景與理論
在資料保護系統中,「金鑰」指的是能夠提供認證加密服務的物件。 每個金鑰都以唯一的 ID(GUID)識別,並攜帶演算法資訊與熵內容。 系統設計中每個金鑰都帶有獨特的熵,但系統無法強制執行這點,我們也必須考慮到開發者可能會透過修改金鑰環中現有金鑰的演算法資訊來手動更改金鑰環的情況。 為了滿足我們的安全需求,資料保護系統採用 密碼學敏捷性概念,允許在多個密碼演算法中安全地使用單一熵值。
大多數支援密碼學敏捷性的系統,會透過在有效載荷中包含演算法的某些識別資訊來達成此目標。 演算法的 OID 通常是很好的選擇。 然而,我們遇到一個問題,就是有多種方式可以指定同一個演算法:「AES」(CNG)以及受管理的 Aes、AesManaged、AesCryptoServiceProvider、AesCng 和 RijndaelManaged(給定特定參數)類別其實都是同一件事,我們需要維護這些類別對應到正確的 OID。 如果開發者想提供自訂演算法(甚至是其他 AES 實作!),他們必須告訴我們它的 OID。 這個額外的註冊步驟讓系統設定特別麻煩。
退一步後,我們決定我們從錯誤的方向來解決問題。 OID 告訴你演算法是什麼,但我們其實不在乎這個。 如果我們需要在兩個不同的演算法中安全地使用單一熵值,我們就不需要知道這些演算法到底是什麼。 我們真正關心的是他們的行為。 任何良好的對稱區塊密碼演算法同時也具有強偽隨機置換(PRP)的特性:當設定輸入(密鑰、鏈接模式、IV和明文)時,密文輸出以極高的概率會與其他使用相同輸入的對稱區塊密碼演算法的密文不同。 同樣地,任何不錯的密鑰雜湊函數同時也是強偽隨機函數(PRF),在給定固定輸入集合的情況下,其輸出將會與任何其他密鑰雜湊函數顯著不同。
我們利用強 PRP 和 PRF 的概念來建立上下文標頭。 在任何特定操作中,這個上下文標識本質上作為演算法的穩定識別,並提供資料保護系統所需的加密靈活性。 此標頭是可再現的,並用於 子金鑰衍生過程的一部分。 根據底層演算法的運作模式,有兩種不同的上下文標頭建構方式。
CBC 模式加密 + HMAC 認證
上下文標頭包含以下元件:
[16 bits] 值 00 00,這是一個標記,代表「CBC 加密 + HMAC 認證」。
[32位元]對稱區塊密碼演算法的金鑰長度(以位元組為單位,大端序)。
[32位元]對稱區塊密碼演算法的區塊大小(以位元組為單位,大端序)。
[32位元]HMAC 演算法的金鑰長度(以字節、大端序為單位)。 (目前金鑰大小總是與消化大小相符。)
[32位元]HMAC 演算法的摘要大小(以位元組為單位,大端序)。
EncCBC(K_E, IV, ""),這是對稱區塊密碼演算法在給定空字串輸入且 IV 為全零向量時的輸出。 的構造K_E如下所述。MAC(K_H, ""),這是給定空字串輸入時 HMAC 演算法的輸出。 的構造K_H如下所述。
理想情況下,我們可以讓K_E和K_H的向量全為零。 然而,我們希望避免底層演算法在執行任何操作前(特別是 DES 和 3DES)先檢查弱鍵的存在,這會排除使用像全零向量這類簡單或可重複的模式。
取而代之的是,我們使用 NIST SP800-108 KDF 的計數器模式(參見 NIST SP800-108,第 5.1 節),並使用零長度的鍵、標籤和上下文,底層 PRF 則是 HMACSHA512。 我們會產生| K_E | + | K_H |位元組的輸出,然後將結果分解成K_E和K_H本身。 數學上,這表示方式如下。
( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")
範例:AES-192-CBC + HMACSHA256
舉例來說,對稱區塊密碼演算法為 AES-192-CBC,驗證演算法為 HMACSHA256。 系統會透過以下步驟產生上下文標頭。
首先,設 ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""),其中 | K_E | = 192 bits 和 | K_H | = 256 bits 依照指定的演算法。 這在下面的例子中引發了 K_E = 5BB6..21DD 和 K_H = A04A..00A9。
5B B6 C9 83 13 78 22 1D 8E 10 73 CA CF 65 8E B0
61 62 42 71 CB 83 21 DD A0 4A 05 00 5B AB C0 A2
49 6F A5 61 E3 E2 49 87 AA 63 55 CD 74 0A DA C4
B7 92 3D BF 59 90 00 A9
接著,在如上所述的 IV = 0* 和 K_E 前提下,計算 Enc_CBC (K_E, IV, "") 以便使用 AES-192-CBC。
result := F474B1872B3B53E4721DE19C0841DB6F
接著,根據如上所示的 K_H 計算 HMACSHA256的 MAC(K_H, "")。
result := D4791184B996092EE1202F36E8608FA8FBD98ABDFF5402F264B1D7211536220C
此後產生完整的上下文標頭如下:
00 00 00 00 00 18 00 00 00 10 00 00 00 20 00 00
00 20 F4 74 B1 87 2B 3B 53 E4 72 1D E1 9C 08 41
DB 6F D4 79 11 84 B9 96 09 2E E1 20 2F 36 E8 60
8F A8 FB D9 8A BD FF 54 02 F2 64 B1 D7 21 15 36
22 0C
此上下文標頭是認證加密演算法對(AES-192-CBC 加密 + HMACSHA256驗證)的指紋。 上述 組成部分 如下:
標記
(00 00)區塊密碼密鑰長度
(00 00 00 18)區塊密碼區塊大小
(00 00 00 10)HMAC 金鑰長度
(00 00 00 20)HMAC 摘要尺寸
(00 00 00 20)區塊密碼 PRP 輸出
(F4 74 - DB 6F)及HMAC PRF 輸出
(D4 79 - end)。
備註
無論演算法實作是由 Windows CNG 或受管理的 SymmetricAlgorithm 與 KeyedHashAlgorithm 類型提供,CBC 模式加密 + HMAC 認證上下文標頭的建構方式相同。 這使得在不同作業系統上執行的應用程式,即使演算法實作不同,也能可靠地產生相同的上下文標頭。 (實務上,KeyedHashAlgorithm 不一定是正式的 HMAC。它可以是任何有鍵雜湊演算法類型。)
範例:3DES-192-CBC + HMACSHA1
首先,設 ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""),其中 | K_E | = 192 bits 和 | K_H | = 160 bits 依照指定的演算法。 這在下面的例子中引發了 K_E = A219..E2BB 和 K_H = DC4A..B464。
A2 19 60 2F 83 A9 13 EA B0 61 3A 39 B8 A6 7E 22
61 D9 F8 6C 10 51 E2 BB DC 4A 00 D7 03 A2 48 3E
D1 F7 5A 34 EB 28 3E D7 D4 67 B4 64
接著,根據上述所提供的IV = 0*和K_E來計算Enc_CBC (K_E, IV, "")的3DES-192-CBC。
result := ABB100F81E53E10E
接著,根據如上所示的 K_H,計算 MAC(K_H, "") 的 HMACSHA1。
result := 76EB189B35CF03461DDF877CD9F4B1B4D63A7555
此會產生完整上下文標頭,即認證加密演算法對的指紋(3DES-192-CBC 加密 + HMACSHA1 驗證),如下所示:
00 00 00 00 00 18 00 00 00 08 00 00 00 14 00 00
00 14 AB B1 00 F8 1E 53 E1 0E 76 EB 18 9B 35 CF
03 46 1D DF 87 7C D9 F4 B1 B4 D6 3A 75 55
各組成部分如下:
標記
(00 00)區塊密碼密鑰長度
(00 00 00 18)區塊加密演算法的區塊大小
(00 00 00 08)HMAC 金鑰長度
(00 00 00 14)HMAC 摘要尺寸
(00 00 00 14)區塊密碼 PRP 輸出
(AB B1 - E1 0E)及HMAC PRF 輸出
(76 EB - end)。
加洛瓦/计数器模式加密 + 认证
上下文標頭包含以下元件:
[16 bits] 值 00 01,代表標記「GCM 加密 + 認證」。
[32位元]對稱區塊密碼演算法的金鑰長度(以位元組為單位,大端序)。
[32位元]驗證加密操作中使用的 nonce 大小(以位元組為單位,大端序)。 對於我們的系統,這個 nonce 的大小已固定為 96 位元。
[32位元]對稱區塊密碼演算法的區塊大小(以位元組為單位,大端序)。 (對於 GCM,這個限制固定在區塊大小 = 128 位元。)
[32位元]認證標籤大小(以位元組為單位,大端序)由認證加密函式產生。 (對我們系統而言,這個設定固定在標籤大小 = 128 位元。)
[128位元]標籤
Enc_GCM (K_E, nonce, ""),即對稱區塊密碼演算法在給定空字串輸入時的輸出,其中 nonce 是一個 96 位元全零向量。
K_E 其推導機制與 CBC 加密 + HMAC 認證情境相同。 然而,由於這裡不存在 K_H,實際上我們擁有的是 | K_H | = 0,演算法會簡化為以下形式。
K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")
範例:AES-256-GCM
首先,設 K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""),其中 | K_E | = 256 bits。
K_E := 22BC6F1B171C08C4AE2F27444AF8FC8B3087A90006CAEA91FDCFB47C1B8733B8
接著,根據上述提供的nonce = 096和K_E,計算Enc_GCM (K_E, nonce, "")的AES-256-GCM認證標籤。
result := E7DCCE66DF855A323A6BB7BD7A59BE45
此後產生完整的上下文標頭如下:
00 01 00 00 00 20 00 00 00 0C 00 00 00 10 00 00
00 10 E7 DC CE 66 DF 85 5A 32 3A 6B B7 BD 7A 59
BE 45
各組成部分如下:
標記
(00 01)區塊密碼密鑰長度
(00 00 00 20)隨機數大小
(00 00 00 0C)區塊密碼區塊大小
(00 00 00 10)認證標籤的大小
(00 00 00 10)和由執行區塊密碼
(E7 DC - end)產生的認證標籤。