Error message
"alg" parameter "ES256" requires curve "prime256v1".
Also printed as
- "alg" parameter "ES384" requires curve "secp384r1".
- "alg" parameter "ES512" requires curve "secp521r1".
Thrown by both `jwt.sign()` and `jwt.verify()`. The required curve is named in OpenSSL's spelling: `prime256v1`, `secp384r1`, `secp521r1`.
jsonwebtoken (Node.js) — Error from jwt.sign() / jwt.verify() key validation (v9+)
What it means
The EC key you passed is on a different curve than the algorithm demands. In JOSE every ECDSA algorithm is tied to exactly one curve: ES256 to P-256 (OpenSSL name `prime256v1`), ES384 to P-384 (`secp384r1`), ES512 to P-521 (`secp521r1`). Since version 9, jsonwebtoken checks the key's curve against the `alg` before signing or verifying, so a mismatched key is rejected up front instead of producing tokens no other library accepts.
Why it happens
A secp256k1 key with ES256
commonsecp256k1 (Bitcoin, Ethereum) is a different 256-bit curve. Its JOSE algorithm is `ES256K` (RFC 8812), which jsonwebtoken does not support; the "256" in ES256 refers to SHA-256 and P-256 only.
A P-384 or P-521 key with ES256
occasionalKeys generated with OpenSSL defaults, a cloud KMS key spec such as `ECC_NIST_P384`, or a certificate key from a CA profile may use a larger curve. Pick the algorithm that matches the key (ES384/ES512) or generate a P-256 key.
The wrong key file was loaded
occasionalSeveral keys in one secrets store, and the service reads the one meant for another purpose — a TLS key, an SSH key, a signing key for another system.
How to fix it
- 1.
Print the key's curve
`asymmetricKeyDetails.namedCurve` reports the curve in OpenSSL naming. Compare it with the algorithm in the token header.
js import { createPublicKey } from "node:crypto"; const key = createPublicKey(pem); console.log(key.asymmetricKeyType, key.asymmetricKeyDetails); // ec { namedCurve: 'prime256v1' } - 2.
Derive the algorithm from the key
If keys of different sizes are in use, choose the JWS algorithm from the key's curve instead of hard-coding ES256, and publish the same `alg` in your JWKS.
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.
Generate a P-256 key when you need ES256
ES256 is the most widely supported ECDSA algorithm in JOSE libraries; a new P-256 key pair takes one command.
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