{"record":{"id":"709b65b2303b95ec","repo":"jwtk/jjwt","slug":"getid-keytype-signing-keys-must-be-type","errorCode":null,"errorMessage":"${getId()} ${keyType(signing)} keys must be ${type.getSimpleName()}s (implement ${type.getName()}). Provided key type: ${key.getClass().getName()}.","messagePattern":"(.+?) (.+?) keys must be (.+?)s \\(implement (.+?)\\)\\. Provided key type: (.+?)\\.","errorType":"validation","errorClass":"InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/AbstractSignatureAlgorithm.java","lineNumber":48,"sourceCode":"\nabstract class AbstractSignatureAlgorithm extends AbstractSecureDigestAlgorithm<PrivateKey, PublicKey>\n        implements SignatureAlgorithm {\n\n    private static final String KEY_TYPE_MSG_PATTERN =\n            \"{0} {1} keys must be {2}s (implement {3}). Provided key type: {4}.\";\n\n    AbstractSignatureAlgorithm(String id, String jcaName) {\n        super(id, jcaName);\n    }\n\n    @Override\n    protected void validateKey(Key key, boolean signing) {\n        // https://github.com/jwtk/jjwt/issues/68:\n        Class<?> type = signing ? PrivateKey.class : PublicKey.class;\n        if (!type.isInstance(key)) {\n            String msg = MessageFormat.format(KEY_TYPE_MSG_PATTERN, getId(),\n                    keyType(signing), type.getSimpleName(), type.getName(), key.getClass().getName());\n            throw new InvalidKeyException(msg);\n        }\n    }\n\n    protected final byte[] sign(Signature sig, InputStream payload) throws Exception {\n        byte[] buf = new byte[2048];\n        int len = 0;\n        while (len != -1) {\n            len = payload.read(buf);\n            if (len > 0) sig.update(buf, 0, len);\n        }\n        return sig.sign();\n    }\n\n    @Override\n    protected byte[] doDigest(final SecureRequest<InputStream, PrivateKey> request) {\n        return jca(request).withSignature(new CheckedFunction<Signature, byte[]>() {\n            @Override\n            public byte[] apply(Signature sig) throws Exception {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/AbstractSignatureAlgorithm.java#L30-L66","documentation":"validateKey enforces that signing uses a PrivateKey and verification uses a PublicKey for the configured signature algorithm. A key of the wrong type throws InvalidKeyException naming the required interface and the actual key class.","triggerScenarios":"Calling jwt.signWith(privateKeyOfWrongType) or a SignatureAlgorithm instance's verify with a PrivateKey, or passing a symmetric SecretKey where an asymmetric key is required.","commonSituations":"Loading the public cert/key when the private key was intended; storing keys in a Map and picking the wrong entry; mixing PEM public/private files; using a SecretKey (HMAC) with an RSA algorithm id.","solutions":["Check the key object: signing requires PrivateKey, verification requires PublicKey (key instanceof check).","Reload the correct half of the key pair from your keystore/PEM.","Use the matching builder APIs: signWith(privateKey) vs verifyWith(publicKey).","For symmetric use cases, use HMAC algorithms (HS256/384/512) with SecretKey instead."],"exampleFix":"// before\nalg.verify(secureRequestWithPrivateKey);\n// after\nPublicKey pub = keyPair.getPublic();\nalg.verify(secureRequest(pub));","handlingStrategy":"validation","validationCode":"if (signing && !(key instanceof PrivateKey)) throw new InvalidKeyException(\"Signing requires a PrivateKey\");\nif (!signing && !(key instanceof PublicKey)) throw new InvalidKeyException(\"Verification requires a PublicKey\");","typeGuard":"boolean isCorrectHalf(Key k, boolean signing) { return signing ? k instanceof PrivateKey : k instanceof PublicKey; }","tryCatchPattern":"try { alg.verify(req); }\ncatch (InvalidKeyException e) { log.error(\"Wrong key half: {}\", e.getMessage()); reloadKeys(); }","preventionTips":["Name key variables explicitly (signingKey/verifyingKey).","Check instanceof PrivateKey before sign calls.","Keep public/private PEM files in clearly named files."],"tags":["invalid-key","signing","verification","jjwt"],"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-14T11:17:12.474Z"}