jwtk/jjwt · error · io.jsonwebtoken.security.InvalidKeyException
EC JWK x,y coordinates do not exist on elliptic curve '%s'.
Error message
EC JWK x,y coordinates do not exist on elliptic curve '%s'. This could be due simply to an incorrectly-created JWK or possibly an attempted Invalid Curve Attack (see https://safecurves.cr.yp.to/twist.html for more information).
What it means
EcPublicJwkFactory.createJwkFromValues validates that the x,y coordinate pair parsed from JWK JSON values lies on the named elliptic curve. If it does not, the JWK was created incorrectly or the input may be an attempted Invalid Curve Attack, so the factory throws InvalidKeyException and refuses to materialize the key.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/EcPublicJwkFactory.java:106
ctx.put(DefaultEcPublicJwk.Y.getId(), y);
return new DefaultEcPublicJwk(ctx);
}
@Override
protected EcPublicJwk createJwkFromValues(final JwkContext<ECPublicKey> ctx) {
ParameterReadable reader = new RequiredParameterReader(ctx);
String curveId = reader.get(DefaultEcPublicJwk.CRV);
BigInteger x = reader.get(DefaultEcPublicJwk.X);
BigInteger y = reader.get(DefaultEcPublicJwk.Y);
ECCurve curve = getCurveByJwaId(curveId);
ECPoint point = new ECPoint(x, y);
if (!curve.contains(point)) {
String msg = jwkContainsErrorMessage(curveId, ctx);
throw new InvalidKeyException(msg);
}
final ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, curve.toParameterSpec());
ECPublicKey key = generateKey(ctx, new CheckedFunction<KeyFactory, ECPublicKey>() {
@Override
public ECPublicKey apply(KeyFactory kf) throws Exception {
return (ECPublicKey) kf.generatePublic(pubSpec);
}
});
ctx.setKey(key);
return new DefaultEcPublicJwk(ctx);
}
}
View on GitHub (pinned to fb71496164)
Solutions
- Verify the source of the JWK data; only trust JWK sets from authenticated/HTTPS key endpoints.
- Fix transcription errors in x/y values and ensure crv matches the coordinates.
- Regenerate the key pair and re-serialize the JWK.
- Keep jjwt up to date — this on-curve check is itself the library's mitigation against invalid curve attacks.
Example fix
// before
// x from curve A, y from curve B (mismatch)
Jwk jwk = Jwks.parser().build().parse("{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"...\",\"y\":\"WRONG\"}");
// after
// re-serialize from a valid key pair
KeyPair kp = kg.generateKeyPair();
Jwk jwk = Jwks.builder().setKey(kp.getPublic()).build(); Defensive patterns
Strategy: validation
Validate before calling
// decode x,y into BigInteger and verify y^2 = x^3 + ax + b (mod p) for the crv curve before parsing
boolean onCurve(BigInteger x, BigInteger y, EllipticCurve c) {
BigInteger p = ((ECFieldFp) c.getField()).getP();
return y.pow(2).subtract(x.pow(3).add(c.getA().multiply(x)).add(c.getB())).mod(p).signum() == 0;
} Try / catch
try {
Jwk<?> jwk = Jwks.parser().build().parse(json);
} catch (io.jsonwebtoken.security.InvalidKeyException e) {
// reject the JWK as malformed or hostile (possible invalid curve attack)
} Prevention
- Only accept JWKs from trusted, TLS-protected endpoints
- Log and reject off-curve coordinates — treat as a security event
- Keep jjwt updated to retain on-curve validation fixes
When it happens
Trigger: Parsing or creating a JWK from map values (e.g. Jwks.parser().parse(...)) where x and y are valid Base64URL integers but not a valid curve point for the crv value; maliciously crafted JWK sets from untrusted sources.
Common situations: Accepting JWKs from third parties without validation; hand-written JWK JSON with a typo in x or y; attackers substituting low-order points to exploit invalid-curve vulnerabilities.
Related errors
- Unable to derive ECPublicKey from ECPrivateKey: ${e.getMessa
- The specified ECKey curve does not match a JWA standard curv
- ECPublicKey's ECPoint does not exist on elliptic curve '%s'
- The specified key byte array is bits which is not secure en
- Unrelated key operations are not allowed. KeyOperation [${in
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/68c86edd55f5caa9.
Report an issue: GitHub.