错误信息
"alg" parameter "ES256" requires curve "prime256v1".
也可能输出为
- "alg" parameter "ES384" requires curve "secp384r1".
- "alg" parameter "ES512" requires curve "secp521r1".
`jwt.sign()` 和 `jwt.verify()` 都会抛出这个错误。所需曲线使用 OpenSSL 的写法:`prime256v1`、`secp384r1`、`secp521r1`。
jsonwebtoken (Node.js) — Error from jwt.sign() / jwt.verify() key validation (v9+)
含义
你传入的 EC 密钥所在的曲线与算法要求的不同。在 JOSE 中,每个 ECDSA 算法都只对应一条曲线:ES256 对应 P-256(OpenSSL 名称为 `prime256v1`),ES384 对应 P-384(`secp384r1`),ES512 对应 P-521(`secp521r1`)。自版本 9 起,jsonwebtoken 会在签名或验证之前对照 `alg` 检查密钥的曲线,因此不匹配的密钥会被提前拒绝,而不会生成其他库都不接受的令牌。
原因
ES256 搭配了 secp256k1 密钥
常见secp256k1(比特币、以太坊)是另一条 256 位曲线。它对应的 JOSE 算法是 `ES256K`(RFC 8812),jsonwebtoken 不支持该算法;ES256 中的“256”只指 SHA-256 和 P-256。
ES256 搭配了 P-384 或 P-521 密钥
偶见用 OpenSSL 默认设置生成的密钥、使用 `ECC_NIST_P384` 等云 KMS 密钥规格创建的密钥,或者按 CA 证书模板生成的证书密钥,都可能使用更大的曲线。选择与密钥相符的算法(ES384/ES512),或者生成 P-256 密钥。
加载了错误的密钥文件
偶见同一个机密存储中有多个密钥,服务读取了用于其他用途的那一个——TLS 密钥、SSH 密钥,或者另一个系统的签名密钥。
修复方法
- 1.
打印密钥的曲线
`asymmetricKeyDetails.namedCurve` 以 OpenSSL 的命名报告曲线。把它与令牌头部中的算法对照。
js import { createPublicKey } from "node:crypto"; const key = createPublicKey(pem); console.log(key.asymmetricKeyType, key.asymmetricKeyDetails); // ec { namedCurve: 'prime256v1' } - 2.
根据密钥确定算法
如果同时在用不同大小的密钥,就根据密钥的曲线选择 JWS 算法,而不是硬编码 ES256,并在 JWKS 中发布同样的 `alg`。
js const ALG_BY_CURVE = { prime256v1: "ES256", secp384r1: "ES384", secp521r1: "ES512" }; const alg = ALG_BY_CURVE[key.asymmetricKeyDetails.namedCurve]; if (!alg) throw new Error("this curve has no JWS algorithm in jsonwebtoken"); const token = jwt.sign(claims, key, { algorithm: alg, expiresIn: "10m" }); - 3.
需要 ES256 时生成 P-256 密钥
ES256 是 JOSE 库中支持最广泛的 ECDSA 算法;生成新的 P-256 密钥对只需一条命令。
bash openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out es256-private.pem openssl pkey -in es256-private.pem -pubout -out es256-public.pem