JWT 指南

我如何在 HS256 與 RS256 之間做 JWT 架構選擇

我比較 HS256 與 RS256 時,不只看演算法名稱,而是看 shared secret、public/private key、signing authority、JWKS、rotation 與 verifier 的 trust boundary。

作者:JWTDecoder.tools最後確認 2026-09-13

編輯語氣說明:第一人稱敘述代表 JWTDecoder.tools 已文件化的驗證工作流程;發布者與組織作者皆為 JWTDecoder.tools。

HS256 ↔ RS256 signing architecture
HS256: shared secret · RS256: private key → sign, public key → verify

我在 HS256 與 RS256 之間做選擇時,不會只問「哪一個比較安全」,而會先問:誰需要簽 token?誰只需要驗證?金鑰會被分發到多少個系統? 這些問題通常比演算法名稱本身更能決定正確架構。

HS256 的 trust model

HS256 使用 HMAC SHA-256。issuer 與 verifier 共用同一個 secret。

Issuer ─┐
        ├─ shared secret → sign / verify
Verifier┘

優點是簡單:沒有 public/private key pair,也不需要 JWKS。

但它有一個很重要的特性:能驗證的人通常也擁有產生有效簽章的能力。 如果多個微服務都拿到同一個 secret,那些服務不只是 verifier,也具備 signing capability。

RS256 的 trust model

RS256 使用 RSA private key 簽章,public key 驗證。

Issuer
  private key → sign
       ↓
      JWT
       ↓
Verifier A/B/C
  public key → verify

這讓我可以把 signing authority 留在 issuer,其他 API 只持有 public key。

當 verifier 數量增加、跨團隊或跨服務時,這種權限分離通常很有價值。

我實際比較的項目

項目HS256RS256
金鑰shared secretprivate/public pair
誰能簽拿到 secret 的系統持有 private key 的 issuer
誰能驗拿到 secret 的系統任何拿到 public key 的 verifier
多服務部署secret 會擴散public key 可安全分發
JWKS通常不適用很適合
Rotationsecret 協調較麻煩kid + JWKS 容易管理

什麼情況我會考慮 HS256

  • issuer 與 verifier 在同一個小型 trust boundary;
  • verifier 數量少;
  • secret distribution 可以嚴格控制;
  • 不需要公開 verification;
  • 架構簡單比 key separation 更重要。

例如單一 backend 自己簽、自己驗,HS256 可以非常合理。

但當我開始把同一個 secret 複製到很多服務,就會重新評估。

什麼情況我更傾向 RS256

  • 一個 issuer 對多個 API 發 token;
  • verifier 不應具有 signing capability;
  • 身分提供者原生提供 JWKS;
  • 需要頻繁 key rotation;
  • 多 region、多團隊或外部 verifier 需要驗證。

這時 private key 可以限制在 issuer,其他系統只拿 public JWK。

我不讓 token 的 alg 決定 verifier policy

不管使用 HS256 還是 RS256,我都會在 server 端先設定 allowed algorithms。

allowed algorithms = ["RS256"]

token header 還沒被驗證,所以它不能自己說「這次改用 HS256」或「這次用 none」。

JWT Security Analyzer 可以用明確 allowlist 檢查 unexpected algorithm。

HS256 的 secret 品質很重要

如果 secret 很短、可猜或直接寫進 source code,演算法本身再標準也沒有用。我會使用高 entropy random secret,並放在適當 secret manager。

我也不會把 production HS256 secret 放進 browser JavaScript。前端是 public client,送到 client 的 secret 就不再能當成真正秘密。

RS256 的 private key 保護同樣重要

RS256 並不會自動安全。private key 如果外洩,攻擊者就可以產生有效 token。

我會限制 private key 的存取、使用 KMS/HSM 或受控 signing environment,並設計 emergency rotation/revocation 流程。

Key rotation 的差異

HS256 換 secret 時,issuer 與所有 verifier 必須協調新舊 secret。

RS256 則常透過 kid + JWKS:

old key → old kid
new key → new kid

JWKS = [old public JWK, new public JWK]

先 publish new public key,再開始用 new private key 簽,最後等 old token 的 lifetime 結束後移除 old key。

完整流程可看 JWT Key Rotation。

我驗證 RS256 JWT 的順序

  1. decode token;
  2. 讀 alg 與 kid;
  3. 確認 expected issuer;
  4. 從 trusted issuer 取得 JWKS;
  5. 在 trusted set 裡用 kid 找 candidate;
  6. 檢查 kty、alg、use、key_ops;
  7. 驗證 signature;
  8. 檢查 iss、aud、exp、nbf。

JWKS Validator 就是為這條流程設計。

我不把效能當第一個選擇條件

在一般 web API 中,資料庫、network 與 business logic 往往比一次 JWT verification 更可能是瓶頸。我不會因為 HS256 通常計算較簡單,就犧牲需要的 trust separation。

反過來,如果只有單一小型 backend,我也不會只是因為 RS256 看起來更「企業級」就增加不必要的 key infrastructure。

我的決策清單

  1. signer 與 verifier 是否在同一 trust boundary?
  2. verifier 是否應該擁有 signing capability?
  3. 有多少 verifier?
  4. key 要怎麼分發?
  5. rotation 時 old/new key 如何 overlap?
  6. 是否已有 OIDC/JWKS infrastructure?
  7. allowed algorithm 在哪裡強制?
  8. issuer/audience/time policy 在哪裡驗證?

我最後選 HS256 或 RS256,不是看哪個名字更流行,而是看哪個模型可以讓 key ownership、signing authority 與 verification responsibility 最清楚。

來源與參考資料

相關指南