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

  1. Verify the source of the JWK data; only trust JWK sets from authenticated/HTTPS key endpoints.
  2. Fix transcription errors in x/y values and ensure crv matches the coordinates.
  3. Regenerate the key pair and re-serialize the JWK.
  4. 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

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


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/68c86edd55f5caa9. Report an issue: GitHub.