jwtk/jjwt · error · io.jsonwebtoken.security.InvalidKeyException
Unable to derive ECPublicKey from ECPrivateKey: ${e.getMessa
Error message
Unable to derive ECPublicKey from ECPrivateKey: ${e.getMessage()} What it means
When creating an EC public JWK from an ECPrivateKey, EcPrivateJwkFactory derives the matching ECPublicKey from the private key's parameters. If KeyFactory fails to derive the public key (bad or missing EC parameters, provider issues), the underlying exception message is wrapped in this InvalidKeyException.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/EcPrivateJwkFactory.java:67
return super.supportsKeyValues(ctx) && ctx.containsKey(DefaultEcPrivateJwk.D.getId());
}
// visible for testing
protected ECPublicKey derivePublic(KeyFactory keyFactory, ECPublicKeySpec spec) throws InvalidKeySpecException {
return (ECPublicKey) keyFactory.generatePublic(spec);
}
protected ECPublicKey derivePublic(final JwkContext<ECPrivateKey> ctx) {
final ECPrivateKey key = ctx.getKey();
return generateKey(ctx, ECPublicKey.class, new CheckedFunction<KeyFactory, ECPublicKey>() {
@Override
public ECPublicKey apply(KeyFactory kf) {
try {
ECPublicKeySpec spec = ECCurve.publicKeySpec(key);
return derivePublic(kf, spec);
} catch (Exception e) {
String msg = "Unable to derive ECPublicKey from ECPrivateKey: " + e.getMessage();
throw new InvalidKeyException(msg, e);
}
}
});
}
@Override
protected EcPrivateJwk createJwkFromKey(JwkContext<ECPrivateKey> ctx) {
ECPrivateKey key = ctx.getKey();
ECPublicKey ecPublicKey;
PublicKey publicKey = ctx.getPublicKey();
if (publicKey != null) {
ecPublicKey = Assert.isInstanceOf(ECPublicKey.class, publicKey, ECPUBKEY_ERR_MSG);
} else {
ecPublicKey = derivePublic(ctx);
}
View on GitHub (pinned to fb71496164)
Solutions
- Use an ECPrivateKey created with ECGenParameterSpec (e.g. secp256r1) so public-key parameters are available.
- Regenerate or re-import the key with a standard provider (SunEC) if the current provider cannot derive the public key.
- Read the wrapped cause (e.getCause().getMessage()) to identify the actual KeyFactory failure.
- If the key comes from an HSM, build the JWK from values (x, y, d, crv) instead of from the Key object.
Example fix
// before
KeyPairGenerator kg = KeyPairGenerator.getInstance("EC"); // no named curve spec
kg.initialize(new ECGenParameterSpec("secp256r1")); // omitted in failing code path
// after
KeyPairGenerator kg = KeyPairGenerator.getInstance("EC");
kg.initialize(new ECGenParameterSpec("secp256r1"));
KeyPair kp = kg.generateKeyPair();
Jwk jwk = Jwks.builder().setKey(kp.getPrivate()).build(); Defensive patterns
Strategy: try-catch
Validate before calling
if (key instanceof ECKey && ((ECKey) key).getParams() == null) {
throw new IllegalArgumentException("ECPrivateKey is missing curve parameters; regenerate with a named curve");
} Try / catch
try {
Jwk<?> jwk = Jwks.builder().setKey(ecPrivateKey).build();
} catch (io.jsonwebtoken.security.InvalidKeyException e) {
// inspect e.getCause() for the KeyFactory failure; build JWK from values instead
} Prevention
- Generate EC keys with ECGenParameterSpec so public parameters exist
- For HSM keys, create JWKs from explicit x/y/d/crv values rather than the Key object
When it happens
Trigger: Building a JWK from an ECPrivateKey whose parameters are incomplete or unsupported, e.g. a private key with null params that cannot resolve the curve, or a provider whose KeyFactory cannot build the ECPublicKeySpec.
Common situations: HSM/PKCS11 EC private keys that refuse to expose public parameters; custom security providers; keys deserialized or constructed without ECParameterSpec.
Related errors
- The specified ECKey curve does not match a JWA standard curv
- ECPublicKey's ECPoint does not exist on elliptic curve '%s'
- EC JWK x,y coordinates do not exist on elliptic curve '%s'.
- derivedKeyBitLength may not exceed ${bitsMsg(MAX_DERIVED_KEY
- Unrelated key operations are not allowed. KeyOperation [${in
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/065838b152330d30.
Report an issue: GitHub.