{"record":{"id":"c597aab87beddf5b","repo":"jwtk/jjwt","slug":"jws-verification-key-must-be-either-a-secretkey-f","errorCode":null,"errorMessage":"JWS verification key must be either a SecretKey (for MAC algorithms) or a PublicKey (for Signature algorithms).","messagePattern":"JWS verification key must be either a SecretKey \\(for MAC algorithms\\) or a PublicKey \\(for Signature algorithms\\)\\.","errorType":"exception","errorClass":"InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java","lineNumber":264,"sourceCode":"    }\n\n    @Override\n    public JwtParserBuilder setSigningKey(String base64EncodedSecretKey) {\n        Assert.hasText(base64EncodedSecretKey, \"signature verification key cannot be null or empty.\");\n        byte[] bytes = Decoders.BASE64.decode(base64EncodedSecretKey);\n        return setSigningKey(bytes);\n    }\n\n    @Override\n    public JwtParserBuilder setSigningKey(final Key key) {\n        if (key instanceof SecretKey) {\n            return verifyWith((SecretKey) key);\n        } else if (key instanceof PublicKey) {\n            return verifyWith((PublicKey) key);\n        }\n        String msg = \"JWS verification key must be either a SecretKey (for MAC algorithms) or a PublicKey \" +\n                \"(for Signature algorithms).\";\n        throw new InvalidKeyException(msg);\n    }\n\n    @Override\n    public JwtParserBuilder verifyWith(SecretKey key) {\n        return verifyWith((Key) key);\n    }\n\n    @Override\n    public JwtParserBuilder verifyWith(PublicKey key) {\n        return verifyWith((Key) key);\n    }\n\n    private JwtParserBuilder verifyWith(Key key) {\n        if (key instanceof PrivateKey) {\n            throw new IllegalArgumentException(DefaultJwtParser.PRIV_KEY_VERIFY_MSG);\n        }\n        this.signatureVerificationKey = Assert.notNull(key, \"signature verification key cannot be null.\");\n        return this;","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java#L246-L282","documentation":"Thrown as InvalidKeyException from DefaultJwtParserBuilder.setSigningKey(Key) when the key is neither a SecretKey (for HMAC/MAC algorithms) nor a PublicKey (for asymmetric signature verification) — e.g. a PrivateKey, or an arbitrary Key implementation. Deprecated in favor of verifyWith(...).","triggerScenarios":"parserBuilder.setSigningKey(key) where key is a PrivateKey (loaded from a keystore for signing), a raw byte array wrapper that isn't a SecretKey, or null/unsupported Key type.","commonSituations":"Developers reusing the same key object they used to sign (a PrivateKey) for verification instead of the corresponding PublicKey; passing raw byte[] instead of constructing a SecretKeySpec; confusion after migrating between MAC and RSA/EC tokens.","solutions":["For asymmetric tokens, pass the corresponding PublicKey: .verifyWith(publicKey).","For HMAC tokens, wrap raw bytes in a SecretKeySpec: new SecretKeySpec(bytes, \"HmacSHA256\") and pass it.","Migrate from the deprecated setSigningKey to verifyWith(Key), which gives clearer errors.","Check which algorithm family the token uses (alg header) to know whether a SecretKey or PublicKey is required."],"exampleFix":"// before\nPrivateKey privateKey = loadPrivateKey();\nJwts.parser().setSigningKey(privateKey).build().parse(jwt); // InvalidKeyException\n// after\nPublicKey publicKey = loadPublicKey(); // matching public key\nJwts.parser().verifyWith(publicKey).build().parse(jwt);\n// or for MAC: Jwts.parser().verifyWith(new SecretKeySpec(secretBytes, \"HmacSHA256\")).build()","handlingStrategy":"type-guard","validationCode":"boolean isUsableVerificationKey(java.security.Key k) {\n    return k instanceof javax.crypto.SecretKey || k instanceof java.security.PublicKey;\n}\nif (!isUsableVerificationKey(key)) throw new IllegalArgumentException(\"Need SecretKey or PublicKey\");","typeGuard":"boolean isVerificationKey(java.security.Key k) {\n    return k instanceof javax.crypto.SecretKey || k instanceof java.security.PublicKey;\n}","tryCatchPattern":"try {\n    parserBuilder.setSigningKey(key);\n} catch (io.jsonwebtoken.security.InvalidKeyException e) {\n    // wrong key type: select PublicKey for RSA/EC tokens or SecretKeySpec for MAC\n}","preventionTips":["Migrate to verifyWith(...); setSigningKey is deprecated","Pair SecretKey with MAC tokens and PublicKey with RSA/EC tokens","Wrap raw secret bytes in SecretKeySpec before passing","Load verification keys from a separate, public-only keystore than signing keys"],"tags":["jwt","key-management","signature-verification","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"}