🎫
← 返回教學列表

如何驗證 JWT 簽名:HS256、RS256 與 ES256

· 標籤: jwt-verification, jwt-signature, hs256, rs256, token-validation

如何驗證 JWT 簽名

JWT 以明文形式攜帶其聲明(claims)。唯一防止偽造的就是簽名。若不驗證,攻擊者可以偽造任意權杖並冒充任何使用者。本指南涵蓋三種最常見的 JWT 簽名演算法以及每種演算法的驗證方式。

驗證流程

無論使用哪種演算法,JWT 簽名驗證都遵循相同的步驟:

  1. . 分割權杖,提取標頭、有效載荷和簽名。
  2. 對標頭進行 Base64url 解碼,讀取 alg 欄位。
  3. 使用該演算法和金鑰,根據標頭和有效載荷重新計算簽名。
  4. 將重新計算的簽名與權杖中的簽名進行比對。
  5. 如果相符,則權杖是真實的。

HS256(HMAC-SHA256)

HS256 是一種對稱演算法 — 同一個密鑰用於建立和驗證簽名。

signature = HMACSHA256(
  base64urlEncode(header) + "." + base64urlEncode(payload),
  secret
)

要進行驗證,使用共享密鑰重新計算 HMAC 並進行比對:

Token:   header.payload.sig
Secret:  "my-shared-secret"

1. Compute: HMACSHA256("header.payload", "my-shared-secret")
2. Compare: computedSignature === sig

安全考量: 密鑰必須保密、定期輪換,且至少具有 256 位元的熵。HS256 不適合微服務架構,因為許多服務都需要共享密鑰。

RS256(RSA-SHA256)

RS256 是非對稱的。簽發者使用私鑰簽名;驗證者使用對應的公鑰進行檢查。

signature = RSASHA256(
  base64urlEncode(header) + "." + base64urlEncode(payload),
  privateKey
)

要進行驗證,使用公鑰:

Token:   header.payload.sig
Public:  "-----BEGIN PUBLIC KEY-----..."

1. Load the RSA public key
2. Verify: RSA_SHA256_verify("header.payload", sig, publicKey)

優勢: 簽名金鑰和驗證金鑰是分離的。任何服務都可以進行驗證而無需持有密鑰。公鑰可以通過 JWKS 端點提供,以便輕鬆輪換。

ES256(ECDSA-SHA256)

ES256 使用 P-256 曲線的 ECDSA。與 RS256 一樣,它是非對稱的。

signature = ECDSA_SHA256(
  base64urlEncode(header) + "." + base64urlEncode(payload),
  privateKey
)

驗證使用 ECDSA P-256 公鑰。ES256 產生的簽名要小得多(64 位元組 vs RSA-2048 的 256 位元組),且驗證速度更快。

演算法比較

| 屬性 | HS256 | RS256 | ES256 | |------|-------|-------|-------| | 金鑰類型 | 對稱(共享密鑰) | 非對稱(RSA 金鑰對) | 非對稱(EC 金鑰對) | | 簽名大小 | 32 位元組 | 256 位元組 | 64 位元組 | | 金鑰分發 | 秘密共享 | 公鑰公開 | 公鑰公開 | | 輪換 | 中等 | 簡單(JWKS) | 簡單(JWKS) | | 使用場景 | 受信任的內部系統 | 分散式 API | 行動裝置、物聯網 |

常見驗證陷阱

  • 演算法混淆攻擊。 如果你的程式碼不加限制地從權杖中讀取 alg,攻擊者可以更改演算法。務必驗證演算法是否與預期值相符。
  • 接受 alg: "none" 某些程式庫會接受未簽名的權杖。請明確拒絕 alg: "none"
  • 簽名截斷。 非常數時間的比對可能通過時間攻擊洩漏資訊。請使用你的 JWT 程式庫內建的比對功能。

線上驗證 JWT 權杖

使用 JWT 解碼器工具來解碼和驗證任何權杖。貼上權杖,查看標頭和有效載荷,並通過提供對應的密鑰或公鑰來驗證簽名。所有處理都在你的瀏覽器中完成。

如何驗證 JWT 簽名:HS256、RS256 與 ES256 - CoolTool