{"record":{"id":"1ad489e827abd87f","repo":"jwtk/jjwt","slug":"jwe-header-epk-value-does-not-represent-a-point-on","errorCode":null,"errorMessage":"JWE Header epk value does not represent a point on the expected curve. Value: ${epk}","messagePattern":"JWE Header epk value does not represent a point on the expected curve\\. Value: (.+?)","errorType":"exception","errorClass":"io.jsonwebtoken.security.InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/EcdhKeyAlgorithm.java","lineNumber":226,"sourceCode":"\n        Assert.notNull(request, \"Request cannot be null.\");\n        JweHeader header = Assert.notNull(request.getHeader(), \"Request JweHeader cannot be null.\");\n        PrivateKey privateKey = Assert.notNull(request.getKey(), \"Decryption PrivateKey cannot be null.\");\n        ParameterReadable reader = new RequiredParameterReader(header);\n        PublicJwk<?> epk = reader.get(DefaultJweHeader.EPK);\n\n        AbstractCurve curve = assertCurve(privateKey);\n        Assert.stateNotNull(curve, \"Internal implementation state: Curve cannot be null.\");\n        Class<?> epkClass = curve instanceof ECCurve ? EcPublicJwk.class : OctetPublicJwk.class;\n        if (!epkClass.isInstance(epk)) {\n            String msg = \"JWE Header \" + DefaultJweHeader.EPK + \" value is not an Elliptic Curve \" +\n                    \"Public JWK. Value: \" + epk;\n            throw new InvalidKeyException(msg);\n        }\n        if (!curve.contains(epk.toKey())) {\n            String msg = \"JWE Header \" + DefaultJweHeader.EPK + \" value does not represent \" +\n                    \"a point on the expected curve. Value: \" + epk;\n            throw new InvalidKeyException(msg);\n        }\n\n        final SecretKey derived = deriveKey(request, epk.toKey(), privateKey);\n\n        DecryptionKeyRequest<SecretKey> unwrapReq = new DefaultDecryptionKeyRequest<>(request.getPayload(),\n                null, request.getSecureRandom(), header, request.getEncryptionAlgorithm(), derived);\n\n        return WRAP_ALG.getDecryptionKey(unwrapReq);\n    }\n}\n","sourceCodeStart":208,"sourceCodeEnd":237,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/EcdhKeyAlgorithm.java#L208-L237","documentation":"During ECDH-ES decryption, after confirming the header's `epk` is the right JWK type, jjwt checks that the ephemeral public key's point actually lies on the recipient key's curve (curve.contains(epk.toKey())). If the point is off-curve, the key material is invalid and decryption is aborted with an InvalidKeyException, since continuing would allow invalid-curve attacks.","triggerScenarios":"Decrypting a JWE whose `epk` header decodes to a point not on the recipient's named curve — e.g. coordinates crafted or corrupted, an epk generated for a different curve (P-256 epk with P-384 recipient key), or truncated/byte-mangled x/y or raw x coordinates.","commonSituations":"Sender and recipient disagree on the curve (crv mismatch); tokens produced by non-compliant libraries that do not validate curve membership; deliberate invalid-curve attack attempts; corrupted tokens in transit.","solutions":["Ensure both parties use the same named curve (crv) for the recipient key and epk.","Re-encrypt the token with a compliant library; do not manually edit header values.","If attacks are a concern, this error is jjwt correctly rejecting an invalid-curve input — audit the token source.","Verify no base64url corruption of the compact token (wrong padding/characters) when transporting it."],"exampleFix":"// before: recipient key on P-384 while sender encrypts with P-256\nECPrivateKey key = (ECPrivateKey) Keys.privateKeyFor(SignatureAlgorithm.ES384);\n// after: use matching curves on both sides\nECPrivateKey key = (ECPrivateKey) Keys.privateKeyFor(SignatureAlgorithm.ES256);","handlingStrategy":"validation","validationCode":"String crv = (String) ((Map<?,?>) header.get(\"epk\")).get(\"crv\");\nif (!expectedCurveId.equals(crv)) throw new IllegalArgumentException(\"epk curve mismatch: \" + crv);","typeGuard":"boolean isPointOnExpectedCurve(Object epk, String expectedCrv) {\n  return epk instanceof Map && expectedCrv.equals(((Map<?,?>)epk).get(\"crv\"));\n}","tryCatchPattern":"try {\n  Jwe<Claims> jwe = Jwts.parser().decryptWith(privateKey).build().parseEncryptedClaims(token);\n} catch (InvalidKeyException e) {\n  // treat as invalid/tampered token: reject and log the curve mismatch\n}","preventionTips":["Use the same named curve on sender and recipient","Never accept tokens from producers that skip curve validation","Guard tokens in transit against corruption (integrity-checked channels)"],"tags":["jwe","ecdh","curve","invalid-key"],"backgroundTag":"invalid-key-format","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"}