{"record":{"id":"d2a9fb4bb046b080","repo":"jwtk/jjwt","slug":"unable-to-derive-edwards-curve-publickey-for-speci","errorCode":null,"errorMessage":"Unable to derive Edwards-curve PublicKey for specified PrivateKey: ${privateKey}","messagePattern":"Unable to derive Edwards-curve PublicKey for specified PrivateKey: (.+?)","errorType":"exception","errorClass":"io.jsonwebtoken.security.InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/EdwardsPublicKeyDeriver.java","lineNumber":44,"sourceCode":"\n/**\n * Derives a PublicKey from an Edwards-curve PrivateKey instance.\n */\nfinal class EdwardsPublicKeyDeriver implements Function<PrivateKey, PublicKey> {\n\n    public static final Function<PrivateKey, PublicKey> INSTANCE = new EdwardsPublicKeyDeriver();\n\n    private EdwardsPublicKeyDeriver() {\n        // prevent public instantiation.\n    }\n\n    @Override\n    public PublicKey apply(PrivateKey privateKey) {\n\n        EdwardsCurve curve = EdwardsCurve.findByKey(privateKey);\n        if (curve == null) {\n            String msg = \"Unable to derive Edwards-curve PublicKey for specified PrivateKey: \" + KeysBridge.toString(privateKey);\n            throw new InvalidKeyException(msg);\n        }\n\n        byte[] pkBytes = curve.getKeyMaterial(privateKey);\n\n        // This is a hack that utilizes the JCE implementations' behavior of using an RNG to generate a new private\n        // key, and from that, the implementation computes a public key from the private key bytes.\n        // Since we already have a private key, we provide a RNG that 'generates' the existing private key\n        // instead of a random one, and the corresponding public key will be computed for us automatically.\n        SecureRandom random = new ConstantRandom(pkBytes);\n        KeyPair pair = curve.keyPair().random(random).build();\n        Assert.stateNotNull(pair, \"Edwards curve generated keypair cannot be null.\");\n        return Assert.stateNotNull(pair.getPublic(), \"Edwards curve KeyPair must have a PublicKey\");\n    }\n\n    private static final class ConstantRandom extends SecureRandom {\n        private final byte[] value;\n\n        public ConstantRandom(byte[] value) {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/EdwardsPublicKeyDeriver.java#L26-L62","documentation":"EdwardsPublicKeyDeriver computes the PublicKey corresponding to a supplied Edwards-curve PrivateKey (needed for X25519 key agreement with only a private key). It first resolves the key's curve via EdwardsCurve.findByKey; if no curve matches, it throws an InvalidKeyException saying the public key cannot be derived.","triggerScenarios":"Calling apply(privateKey) (e.g. during ECDH-ES sender-side epk generation) with a PrivateKey that is not an Edwards curve key, or an Edwards key whose encoding the resolver cannot recognize.","commonSituations":"Passing an EC or RSA private key into an X25519/EdDSA key-agreement flow; keys loaded from PKCS#12/PEM with unexpected formats; provider incompatibilities making the key's encoded form unrecognizable.","solutions":["Pass an actual X25519/X448/Ed25519/Ed448 PrivateKey; generate with Jwts.SIG.X25519.keyPair() etc.","Check the key's algorithm string and encoded bytes before calling; only OKP keys are supported here.","Re-export/re-import the key in standard PKCS#8 format so it can be recognized.","Verify a JCE provider supporting the curve is installed."],"exampleFix":"// before\nPublicKey pub = deriver.apply(ecPrivateKey);\n// after\nKeyPair kp = Jwts.SIG.X25519.keyPair().build();\nPublicKey pub = deriver.apply(kp.getPrivate());","handlingStrategy":"validation","validationCode":"EdwardsCurve curve = EdwardsCurve.findByKey(privateKey);\nif (curve == null) throw new IllegalArgumentException(\"Cannot derive public key: not an Edwards private key\");","typeGuard":"boolean isEdwardsPrivateKey(PrivateKey k) {\n  return EdwardsCurve.findByKey(k) != null;\n}","tryCatchPattern":"try {\n  PublicKey pub = new EdwardsPublicKeyDeriver().apply(privateKey);\n} catch (InvalidKeyException e) {\n  // pass a proper OKP private key instead\n}","preventionTips":["Only pass X25519/X448/Ed25519/Ed448 private keys to the deriver","Import keys in standard PKCS#8 format","Verify provider support for the curve"],"tags":["edwards-curve","key-derivation","invalid-key"],"backgroundTag":"invalid-key-type","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}