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

  1. Use an ECPrivateKey created with ECGenParameterSpec (e.g. secp256r1) so public-key parameters are available.
  2. Regenerate or re-import the key with a standard provider (SunEC) if the current provider cannot derive the public key.
  3. Read the wrapped cause (e.getCause().getMessage()) to identify the actual KeyFactory failure.
  4. 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

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


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