簡介 JWS

JWS 的全名為 JSON Web Signature,定義在 RFC 7515 裡面,主要定義了資訊的格式以及序列化(serialization)的方法。從名字可以看得出,它有使用到數位簽章技術,或是它也可以使用訊息驗證碼來確保資料的來源以及完整性。

JWS 包含了三組內容:

  • JOSE Header
  • JWS Payload
  • JWS Signature

JOSE Header 裡則是由下列兩種 Header 聯集而成

  • JWS Protected Header
  • JWS Unprotected Header

JWS Payload 一般會存放 claim。JWS Signature 則是依演算法對 JWS Protected Header 與 JWS Payload 做簽章後,再編碼的內容。如果演算法為 none 的話,則 JWS Signature 會是一個空字串。

而序列化的方法有兩種:

  • JWS Compact Serialization
  • JWS JSON Serialization

JWS 需要了解的主要是 JOSE Header 的定義、序列化的方式、以及如何驗證簽章。

JOSE Header

與 claim 類似,JOSE Header 也分為三類:

  1. Registered Header Parameter,RFC 裡預定義的 Header
  2. Public Header Parameter,在 IANA - JSON Object Signing and Encryption (JOSE) 公開註冊表上的 Header
  3. Private Header Parameter,除了上面兩種以外的 Header,通常是產生 JWS 與使用 JWS 雙方私下的協議,但不建議使用

而在 section 4.1 有列出預定義的 JOSE Header 有哪些,以下是比較常見的:

Header Full name 中文
alg Algorithm 簽章演算法,比方說 RS256
jku JWK Set URL 一個可以拿到 JWK Set 的 URL
jwk JSON Web Key 一個代表 JWK 的 JSON 資料
kid Key ID 如果有多個 JWK,則此 kid 應該會與某個 JWK 的 kid 相同
typ Type 這個 token 的格式,一般會設定成 JWT
cty Content type 一般不會設定,但如果 payload 裡面是另一個 JWT 時,這裡可以設定成 JWT
crit Critical 值為一個陣列,內容為 Header Name,主要目的是讓接受者檢查關鍵的 Header 是否支援

對 X.509 不熟,且這次鐵人賽應該沒時間研讀,所以相關的資訊會先跳過。

而 JWS Protected Header 與 JWS Unprotected Header 的差別為:

Header Type 完整性保護 序列化支援
JWS Protected Header JWS Compact Serialization / JWS JSON Serialization
JWS Unprotected Header JWS JSON Serialization

Serialization

傳輸資料時,通常都會做序列化。方法有兩種,一種是精簡格式 JWS Compact Serialization ,也就是類似 xxx.yyy.zzz 這個樣子:

BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload) || '.' || BASE64URL(JWS Signature)

另一種則是 JWS JSON Serialization,內容只有 JSON encode,裡面又分 GeneralFlattened 兩種格式。

General 大概長的像下面這樣

{
"payload": "<payload contents>",
"signatures": [
{
"protected": "<integrity-protected header 1 contents>",
"header": "<non-integrity-protected header 1 contents>",
"signature": "<signature 1 contents>"
},
{
"protected": "<integrity-protected header n contents>",
"header": "<non-integrity-protected header n contents>",
"signature": "<signature n contents>"
}
]
}

Flattened 則有點像 Compact 的 JSON 版:

{
"payload": "<payload contents>",
"protected": "<integrity-protected header contents>",
"header": "<non-integrity-protected header contents>",
"signature": "<signature contents>"
}

從上面的格式也可以發現,JWS 是有支援放多個簽章的。但只有 General JWS JSON Serialization 支援。

下面是一個簡單的序列化比較表:

Serialization 支援 JWS Unprotected Header 多個簽章 URL 安全 大小
JWS Compact Serialization No No Yes
General JWS JSON Serialization Yes Yes No
Flattened JWS JSON Serialization Yes No No

從這個比較表可以知道 General 資訊比 Flattened 或 Compact 都來得完整,但就會大很多;而使用 JSON Serialization 時,會有編碼上的問題,所以 HTTP 傳輸通常還是 Compact 比較常見。

參考資料