{"record":{"id":"f839c82c56eb6f42","repo":"jwtk/jjwt","slug":"invalid-id-encoded-publickey-privatekey-leng","errorCode":null,"errorMessage":"Invalid ${id} encoded ${PublicKey|PrivateKey} length. Should be ${expected}, found ${actual}.","messagePattern":"Invalid (.+?) encoded (.+?) length\\. Should be (.+?), found (.+?)\\.","errorType":"exception","errorClass":"io.jsonwebtoken.security.InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/EdwardsCurve.java","lineNumber":253,"sourceCode":"                }\n            }\n            Assert.eq(keyLen, this.encodedKeyByteLength, \"Invalid key length.\");\n            byte[] result = Arrays.copyOfRange(encoded, i, i + keyLen);\n            keyLen = Bytes.length(result);\n            Assert.eq(keyLen, this.encodedKeyByteLength, \"Invalid key length.\");\n            return result;\n        } finally {\n            Bytes.clear(encoded);\n        }\n    }\n\n    private void assertLength(byte[] raw, boolean isPublic) {\n        int len = Bytes.length(raw);\n        if (len != this.encodedKeyByteLength) {\n            String msg = \"Invalid \" + getId() + \" encoded \" + (isPublic ? \"PublicKey\" : \"PrivateKey\") +\n                    \" length. Should be \" + Bytes.bytesMsg(this.encodedKeyByteLength) + \", found \" +\n                    Bytes.bytesMsg(len) + \".\";\n            throw new InvalidKeyException(msg);\n        }\n    }\n\n    public PublicKey toPublicKey(byte[] x, Provider provider) {\n        assertLength(x, true);\n        final byte[] encoded = Bytes.concat(this.PUBLIC_KEY_ASN1_PREFIX, x);\n        final X509EncodedKeySpec spec = new X509EncodedKeySpec(encoded);\n        JcaTemplate template = new JcaTemplate(getJcaName(), provider);\n        return template.generatePublic(spec);\n    }\n\n    KeySpec privateKeySpec(byte[] d, boolean standard) {\n        byte[] prefix = standard ? this.PRIVATE_KEY_ASN1_PREFIX : this.PRIVATE_KEY_JDK11_PREFIX;\n        byte[] encoded = Bytes.concat(prefix, d);\n        return new PKCS8EncodedKeySpec(encoded);\n    }\n\n    public PrivateKey toPrivateKey(final byte[] d, Provider provider) {","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/EdwardsCurve.java#L235-L271","documentation":"Raw Edwards curve keys have a fixed encoded length per curve (e.g. 32 bytes for Ed25519/X25519, 57 for Ed448/X448). assertLength is called from toPublicKey/toPrivateKey and rejects raw x or d byte arrays whose length does not match the curve's expected encodedKeyByteLength, throwing an InvalidKeyException.","triggerScenarios":"Calling EdwardsCurve.toPublicKey(byte[] x)/toPrivateKey(byte[] d) (directly or via Jwk parsing of an OKP JWK's x/d) with a byte array that is shorter or longer than the curve's canonical size — e.g. 64-byte signature instead of a 32-byte key, hex/base64 decoded incorrectly, or an Ed25519 key parsed as Ed448.","commonSituations":"Decoding the JWK x value with the wrong base64 variant (standard vs base64url) or with whitespace; concatenating seed+public key (64 bytes) and passing it as the private key; assuming all curves use 32-byte keys.","solutions":["Check the byte array length and trim/pad to the curve's canonical size (32 bytes for 255519-family, 57 for 448-family).","Decode the JWK value with a proper base64url decoder without padding (e.g. io.jsonwebtoken.lang.Base64Url or java.util.Base64.getUrlDecoder).","Confirm you are using the curve instance matching the key's crv (EdwardsCurve.Ed25519 for 32-byte keys, not Ed448).","If you have a 64-byte seed+pub concatenation, use only the first 32 bytes for the private key."],"exampleFix":"// before\nbyte[] d = Base64.getDecoder().decode(jwk.get(\"d\")); // wrong decoder, wrong length\nPrivateKey pk = EdwardsCurve.Ed25519.toPrivateKey(d, null);\n// after\nbyte[] d = Base64.getUrlDecoder().decode((String) jwk.get(\"d\"));\nif (d.length != 32) throw new IllegalArgumentException(\"Ed25519 private key must be 32 bytes\");\nPrivateKey pk = EdwardsCurve.Ed25519.toPrivateKey(d, null);","handlingStrategy":"validation","validationCode":"if (d.length != 32) { // Ed25519/X25519\n  throw new IllegalArgumentException(\"Expected 32-byte raw key, got \" + d.length);\n}","typeGuard":"boolean hasCanonicalLength(byte[] raw, int expected) {\n  return raw != null && raw.length == expected; // 32 for 25519-family, 57 for 448-family\n}","tryCatchPattern":"try {\n  PrivateKey pk = EdwardsCurve.Ed25519.toPrivateKey(d, null);\n} catch (InvalidKeyException e) {\n  // length mismatch: fix decoding / curve selection\n}","preventionTips":["Use base64url decoding (no padding) for JWK x/d values","Know your curve's canonical key length (32 vs 57 bytes)","Never pass seed||public (64-byte) blobs as private keys"],"tags":["ed25519","key-length","base64url","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"}