{"record":{"id":"86051d4ae2f64758","repo":"jwtk/jjwt","slug":"unable-to-determine-jwa-standard-elliptic-curve-fo","errorCode":null,"errorMessage":"Unable to determine JWA-standard Elliptic Curve for ${type}key [${key}]","messagePattern":"Unable to determine JWA-standard Elliptic Curve for (.+?)key \\[(.+?)\\]","errorType":"exception","errorClass":"io.jsonwebtoken.security.InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/EcdhKeyAlgorithm.java","lineNumber":164,"sourceCode":"        }\n    }\n\n    @Override\n    protected String getJcaName(Request<?> request) {\n        if (request instanceof SecureRequest) {\n            return ((SecureRequest<?, ?>) request).getKey() instanceof ECKey ? super.getJcaName(request) : XDH_JCA_NAME;\n        } else {\n            return request.getPayload() instanceof ECKey ? super.getJcaName(request) : XDH_JCA_NAME;\n        }\n    }\n\n    private static AbstractCurve assertCurve(Key key) {\n        Curve curve = StandardCurves.findByKey(key);\n        if (curve == null) {\n            String type = key instanceof PublicKey ? \"encryption \" : \"decryption \";\n            String msg = \"Unable to determine JWA-standard Elliptic Curve for \" + type + \"key [\" +\n                    KeysBridge.toString(key) + \"]\";\n            throw new InvalidKeyException(msg);\n        }\n        if (curve instanceof EdwardsCurve && ((EdwardsCurve) curve).isSignatureCurve()) {\n            String msg = curve.getId() + \" keys may not be used with ECDH-ES key agreement algorithms per \" +\n                    \"https://www.rfc-editor.org/rfc/rfc8037#section-3.1.\";\n            throw new InvalidKeyException(msg);\n        }\n        return Assert.isInstanceOf(AbstractCurve.class, curve, \"AbstractCurve instance expected.\");\n    }\n\n    @Override\n    public KeyResult getEncryptionKey(KeyRequest<PublicKey> request) throws SecurityException {\n        Assert.notNull(request, \"Request cannot be null.\");\n        JweHeader header = Assert.notNull(request.getHeader(), \"Request JweHeader cannot be null.\");\n        PublicKey publicKey = Assert.notNull(request.getPayload(), \"Encryption PublicKey cannot be null.\");\n\n        Curve curve = assertCurve(publicKey);\n        // note: we don't need to validate if specified key's point is on a supported curve here\n        // because that will automatically be asserted when using Jwks.builder().... below","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/EcdhKeyAlgorithm.java#L146-L182","documentation":"Thrown by EcdhKeyAlgorithm.assertCurve when StandardCurves.findByKey cannot map the supplied key to any JWA-standard elliptic curve (P-256, P-384, P-521, X25519, etc.) during ECDH-ES key agreement for JWE. The key passed as the ECDH-ES encryption/decryption key is not recognized as a key on a supported curve — wrong key type, unsupported curve, or a provider key without extractable EC/XEC parameters. The message includes 'encryption ' or 'decryption ' depending on whether a PublicKey or PrivateKey was given.","triggerScenarios":"Calling Jwts.builder().encryptWith(key, Jwts.KEYDIR.ECDH_ES, enc) with a PublicKey on a non-standard curve, or Jwts.parser().decryptWith(key,...) with a PrivateKey JJWT cannot map — e.g. an RSA key, a raw byte[] key, a non-EC asymmetric key, or an EC key from a custom provider whose params JJWT can't read.","commonSituations":"Passing an RSA or secret key where an EC/X25519 public key is required for ECDH-ES; using a custom curve key not among JWA's standard curves; keys loaded from a provider (HSM/PKCS11) lacking the parameters StandardCurves.findByKey inspects; mixing up key pairs so a decryption PrivateKey of the wrong type is supplied.","solutions":["Use an EC P-256/P-384/P-521 or X25519 key pair for ECDH-ES: generate with Jwts.SIG.EC or StandardCurves, e.g. Jwts.KEY.EC pairs","Check the key type at the call site (instanceof ECPublicKey / XECPublicKey) and log the algorithm before encrypting/decrypting","If the key comes from a custom provider, wrap/convert it to a standard java.security.interfaces EC/XEC key carrying its parameters","Verify the JWA key algorithm id matches: ECDH_ES/ECDH_ES+A128KW etc. require elliptic curve keys, not octet or RSA keys"],"exampleFix":"// before: wrong key type for ECDH-ES\nKeyPair kp = Jwts.KEY.RSA.keyPair().build();\nJwts.builder().encryptWith(kp.getPublic(), Jwts.KEYDIR.ECDH_ES, A256GCM);\n// after: use an EC key pair\nKeyPair kp = Jwts.SIG.ES256.keyPair().build(); // P-256\nString jwe = Jwts.builder().encryptWith(kp.getPublic(),\n    Jwts.KEYDIR.ECDH_ES, Jwts.Enc.A256GCM).compact();","handlingStrategy":"type-guard","validationCode":"// assert the key is usable for ECDH-ES before encrypting\nstatic void requireCurveKey(Key k) {\n    boolean ok = k instanceof java.security.interfaces.ECPublicKey\n        || k instanceof java.security.interfaces.XECPublicKey\n        || k instanceof java.security.interfaces.ECPrivateKey\n        || k instanceof java.security.interfaces.XECPrivateKey;\n    if (!ok) throw new IllegalArgumentException(\"ECDH-ES requires an EC or XEC key, got \" + k.getAlgorithm());\n}","typeGuard":"boolean isEcdhCapableKey(Key k) {\n    return k instanceof java.security.interfaces.ECPublicKey\n        || k instanceof java.security.interfaces.XECPublicKey\n        || k instanceof java.security.interfaces.ECPrivateKey\n        || k instanceof java.security.interfaces.XECPrivateKey;\n}","tryCatchPattern":"try {\n    return Jwts.parser().decryptWith(privKey).build().parseEncryptedClaims(jwe).getPayload();\n} catch (InvalidKeyException e) {\n    throw new KeyConfigException(\"key not on a JWA-standard curve for ECDH-ES\", e);\n}","preventionTips":["Generate key material with JJWT (Jwts.SIG.EC keyPair / X25519) to guarantee standard curves","Never pass RSA or SecretKey instances to ECDH-ES algorithms","Be careful with provider-backed (HSM/PKCS11) keys that may not expose curve parameters","Unit-test encrypt/decrypt round trips with the exact keys loaded in production"],"tags":["jwt","jwe","ecdh","key-management","invalid-key"],"backgroundTag":"invalid-argument-value","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}