簡介 JWE

JWS 能保護資料的完整性,但資料傳輸過程是明碼傳輸,因此有心人士還是有辦法截取 JWS Payload 裡的內容做其他利用。如果內容也不希望被其他人看到的話,那還有另一個選擇就是 JWE--RFC 7516 - JSON Web Encryption

相較於 JWS,JWE 的一切資訊都顯得複雜很多,如資訊的組成就有六組:

  • JOSE Header
  • JWE Encrypted Key
  • JWE Initialization Vector
  • JWE AAD
  • JWE Ciphertext
  • JWE Authentication Tag

跟 JWS 一樣,也有 JOSE Header,但它是下面三種 Header 聯集而成,也比 JWS 複雜:

  • JWE Protected Header
  • JWE Shared Unprotected Header
  • JWE Per-Recipient Unprotected Header

而序列化的方法跟 JWS 類似,分成兩種:

  • JWE Compact Serialization
  • JWE JSON Serialization

雖然比較複雜,但了解上面定義的這些方法,大概就可以了解 JWE 的結構為何了。

JOSE Header

JOSE Header 跟 JWS 一樣有分三種類型,就不重覆說明了,註冊表也一樣可以查 IANA - JSON Object Signing and Encryption (JOSE) 公開註冊表。

而在 RFC 7516 section 4.1 定義的 Header 也與 JWS 大同小異,這裡補充多出來的:

Header Full name 中文
enc Encryption Algorithm 關聯數據認證加密演算法,如 A256GCM
zip Compression Algorithm 壓縮演算法,目前只有 DEFDEFLATE)一種

關聯數據認證加密 參考維基百科說明,大概理解為結合[加密][Day 08]與[訊息驗證碼][Day 10]的功能,產生出帶有認證功能的密文。

因 JWE 有定義收件人(recipient)的屬性,所以會有 Per-RecipientShared 的差異。三種 Header 類型的差異如下:

Header Type 完整性保護 收件人 序列化支援
JWE Protected Header 全部 JWE Compact Serialization / JWE JSON Serialization
JWE Shared Unprotected Header 全部 JWE JSON Serialization
JWE Per-Recipient Unprotected Header 單一 JWE JSON Serialization

資料結構上,除了跟 JWS 相同的 JOSE Header 以外,其他都是 JWE 特有的內容。

Section 說明
JWE Encrypted Key 加密過後的密鑰,演算法不支援則會是空的
JWE Initialization Vector 加密的時候使用的初始化向量,演算法不支援則會是空的
JWE AAD 完整性保護的額外參數,只有在 JWE JSON Serialization 才能使用
JWE Ciphertext 密文
JWE Authentication Tag 身分驗證的標記,使用附加的身分驗證資料,對明文加密而來的

Serialization

與 JWS 類似,分為 JWE Compact Serialization 與 JWE JSON Serialization 兩種。JWE Compact Serialization 比 JWS Compact Serialization 多了兩個參數。

BASE64URL(UTF8(JWE Protected Header)) || '.' ||
BASE64URL(JWE Encrypted Key) || '.' ||
BASE64URL(JWE Initialization Vector) || '.' ||
BASE64URL(JWE Ciphertext) || '.' ||
BASE64URL(JWE Authentication Tag)

而 JWE JSON Serialization 也是分為 General 與 Flattened 兩種格式。

General JWE JSON Serialization 官方範例如下:

{
"protected": "<integrity-protected shared header contents>",
"unprotected": "<non-integrity-protected shared header contents>",
"recipients": [
{
"header": "<per-recipient unprotected header 1 contents>",
"encrypted_key": "<encrypted key 1 contents>"
},
{
"header": "<per-recipient unprotected header N contents>",
"encrypted_key": "<encrypted key N contents>"
}
],
"aad": "<additional authenticated data contents>",
"iv": "<initialization vector contents>",
"ciphertext": "<ciphertext contents>",
"tag": "<authentication tag contents>"
}

Flattened JWE JSON Serialization 官方範例如下:

{
"protected": "<integrity-protected header contents>",
"unprotected": "<non-integrity-protected header contents>",
"header": "<more non-integrity-protected header contents>",
"encrypted_key": "<encrypted key contents>",
"aad": "<additional authenticated data contents>",
"iv": "<initialization vector contents>",
"ciphertext": "<ciphertext contents>",
"tag": "<authentication tag contents>"
}

從這兩個範例可以了解,先前有提到 JWE 定義的 recipients 參數,只能用在 General JWE JSON Serialization。

下面是一個簡單的序列化比較表,其實跟 JWS 差異不大:

Serialization 支援 JWE AAD 支援 JWE Shared Unprotected Header 支援 JWE Per-Recipient Unprotected Header URL 安全 大小
JWE Compact Serialization No No No Yes
General JWE JSON Serialization Yes Yes Yes No
Flattened JWE JSON Serialization Yes Yes No No

從這張表可以了解,沒有特別需求的話,還是 JWE Compact Serialization 比較適用。但如果有需要特殊的參數如 JWE AAD,甚至是 JWE Per-Recipient Unprotected Header 的話,則就得考慮 JWE JSON Serialization。

只是實務上,最常使用的還是 JWS + JWS Compact Serialization。

參考資料