「公鑰……到底放在哪裡了?」

在使用 RSA 這類公鑰方式做 JWT 簽章驗證時,總會遇到同一道難題:「公鑰該怎麼安全地發佈?」「輪替金鑰時,難道每台伺服器的設定都要改一次?」

JWKS(JSON Web Key Set) 正是為了解決這個問題而生。JWKS 生成工具 能完全在瀏覽器內產生 RSA 金鑰對,當場同時取得 JWKS 格式(公鑰)與 PEM 格式(私鑰)。

JWKS(JSON Web Key Set)是什麼?

JWKS:公鑰的「展示櫃」

JWKS 是「以 JSON 格式撰寫的一組金鑰」。驗證伺服器(Auth0、Cognito 等)會在一個固定的網址——通常是 /.well-known/jwks.json——公開這份 JSON,任何需要驗證 token 的 API 伺服器都能從那裡取得。

JWKS 為什麼方便

  1. 自動輪替——輪替金鑰時,只需要換掉端點背後的內容即可。API 伺服器只要查詢該網址,就能自動取得最新的金鑰。
  2. 多把金鑰並存——「舊」金鑰與「新」金鑰可以同時存在,讓過渡期更順暢。
  3. 業界標準——OAuth 2.0 與 OIDC 廣泛採用,因此大多數函式庫都內建支援。

JWKS 內部:每個欄位的意義

{
  "keys": [
    {
      "kty": "RSA",
      "n": "0vx7agoebGcQ...",
      "e": "AQAB",
      "kid": "f47ac10b-...",
      "use": "sig",
      "alg": "RS256",
      "key_ops": ["verify"]
    }
  ]
}
欄位作用
kty金鑰類型(如 RSA)
neRSA 公鑰本體(模數與公開指數)
kid金鑰 ID。與 JWT 標頭比對,用來選擇該用哪把金鑰驗證——是金鑰輪替的關鍵
use用途。簽章驗證用是 sig(加密用則是 enc
algkey_ops宣告演算法與允許的操作,防止驗證端誤用

keys 是一個陣列,因此在輪替期間新舊兩把金鑰可以並存,靠 JWT 標頭中的 kid 來區分。

在瀏覽器中產生金鑰對

JWKS 生成工具 結合 jose 函式庫與 Web Crypto API,當場產生 RSA 2048 位元(用於 RS256 簽章)的金鑰對。

  • 公鑰(JWKS 格式)——可作為 /.well-known/jwks.json 的模擬資料使用
  • 私鑰(PEM 格式)——可用於簽署 JWT
  • 若未指定 kid,系統會自動產生一個隨機 ID

產生過程完全在瀏覽器內完成,私鑰不會經過網路傳輸。很適合用來架設本機的模擬驗證伺服器,或替 JWT 驗證邏輯撰寫單元測試。

JWKS 在 JWT 簽章驗證中的運作流程

  1. 驗證伺服器發行 JWT
  2. JWT 標頭中會帶有 kid,標示是用哪把金鑰簽署的
  3. API 伺服器從 JWKS 端點取得公鑰清單
  4. 選出 kid 相符的公鑰
  5. 用該公鑰驗證 JWT 的簽章

這樣的設計讓 API 伺服器完全不需要持有私鑰。私鑰只留在驗證伺服器那一側,驗證端只需要公鑰——職責劃分得很乾淨。JWT 的 payload 本身只是經過 Base64URL 編碼、並未加密,這一點只要用 JWT 解碼工具 檢視實際的 token 就能很直觀地理解。

使用 JWKS 時要注意的地方

  • JWT 標頭的 kid 是否與 JWKS 中的 kid 一致
  • alg 是否是預期的簽章演算法
  • JWKS 的取得結果是否有適當快取
  • 金鑰輪替期間,是否讓新舊金鑰暫時並存
  • 是否已決定何時要移除已失效的金鑰

尤其在金鑰輪替期間,會有一段時間同時存在用舊金鑰簽署的 JWT 與用新金鑰簽署的 JWT。這段期間內,通常會在 JWKS 中同時公開兩把公鑰,讓兩種 JWT 都能被驗證。

常見問題

可以把私鑰放進 JWKS 嗎?

不行。對外公開的 JWKS 應該只包含用於簽章驗證的公鑰。私鑰只能由發行 JWT 的一方持有,絕不能出現在瀏覽器或 API 使用者能看到的地方。

kid 是必須的嗎?

一旦要管理多把金鑰,kid 就非常重要。透過比對 JWT 標頭的 kid 與 JWKS 項目的 kid,驗證端才能判斷該用哪把公鑰。如果預期未來會輪替金鑰,建議一開始就加上 kid

本機開發用的 JWKS 該怎麼建立?

JWKS 生成工具 產生測試用的金鑰對,把公鑰那一側當作 JWKS 使用即可。請將開發用與正式環境用的金鑰分開管理,切勿貼上或分享正式環境的私鑰。

產生出來的金鑰可以直接用在正式環境嗎?

不建議。這個工具的用途是開發、測試與學習。雖然產生過程完全在瀏覽器內完成、金鑰不會外流,但正式環境的簽章金鑰應該在受管理的環境(例如 HSM 或 KMS)中產生與保管。

總結

  • JWKS 以 JSON 格式發佈公鑰,kid 是金鑰輪替的關鍵
  • usealgkey_ops 是用來防止誤用的宣告
  • 驗證端不需要持有私鑰,只要用 JWKS 取得的公鑰就能完成簽章驗證
  • 輪替期間,新舊金鑰會同時存在於 JWKS 中

不必每次都重新回想 OpenSSL 的參數,直接在這裡產生您需要的金鑰吧。