跳到主要内容
ecdsa.com
jose (JavaScript)JWT 库

错误信息

signature verification failed

jose (JavaScript) — JWSSignatureVerificationFailed, code ERR_JWS_SIGNATURE_VERIFICATION_FAILED

含义

jose 成功解析了 JWS 并执行了密码学检查,但用它选中的密钥无法验证该签名。结构、算法和密钥类型都没有问题——只是数学运算对不上,这说明问题出在密钥上,或者被签名的字节遭到了改动。

原因

修复方法

  1. 1.

    按 kid 从颁发者的 JWKS 中查找密钥

    让 jose 为每个令牌挑选正确的密钥,而不是手动固定某一个密钥;createRemoteJWKSet 会缓存密钥,并在密钥轮换时刷新。

    js
    import { createRemoteJWKSet, jwtVerify } from "jose";
    
    const jwks = createRemoteJWKSet(new URL("https://issuer.example/.well-known/jwks.json"));
    const { payload } = await jwtVerify(token, jwks, {
      algorithms: ["ES256"],
      issuer: "https://issuer.example",
    });
  2. 2.

    如果用 node:crypto 签名,就输出原始 r‖s

    对于自定义的签名代码,请求 IEEE P1363 格式的输出,使签名成为 JWS 要求的 64 字节格式——或者通过检查第三段的长度,核实签名代码实际输出的是什么。

    js
    import { sign } from "node:crypto";
    
    const sig = sign("sha256", Buffer.from(signingInput), {
      key: privateKey,
      dsaEncoding: "ieee-p1363", // raw r||s, 64 bytes for P-256
    });
  3. 3.

    检查签名段的结构

    解码令牌的第三段:64 字节表示原始 r‖s(对 ES256 来说是正确的);以 0x30 开头、约 70 字节则表示 DER。下方的 DER ⇄ 原始格式转换器会显示 r 和 s 的值,并在两种格式之间转换。

相关错误

浏览完整的签名错误库