{"record":{"id":"9f60f07d99303ad1","repo":"jwtk/jjwt","slug":"mac-keytype-keys-must-be-secretkey-instances","errorCode":null,"errorMessage":"MAC ${keyType} keys must be SecretKey instances.  Specified key is of type ${k.getClass().getName()}","messagePattern":"MAC (.+?) keys must be SecretKey instances\\.  Specified key is of type (.+?)","errorType":"validation","errorClass":"InvalidKeyException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/security/DefaultMacAlgorithm.java","lineNumber":161,"sourceCode":"        if (!generic && isJwaStandard() && !isJwaStandardJcaName(name)) {\n            throw new InvalidKeyException(\"The \" + keyType(signing) + \" key's algorithm '\" + name +\n                    \"' does not equal a valid HmacSHA* algorithm name or PKCS12 OID and cannot be used with \" +\n                    getId() + \".\");\n        }\n    }\n\n    @Override\n    protected void validateKey(Key k, boolean signing) {\n\n        final String keyType = keyType(signing);\n        if (k == null) {\n            throw new IllegalArgumentException(\"MAC \" + keyType + \" key cannot be null.\");\n        }\n\n        if (!(k instanceof SecretKey)) {\n            String msg = \"MAC \" + keyType + \" keys must be SecretKey instances.  Specified key is of type \" +\n                    k.getClass().getName();\n            throw new InvalidKeyException(msg);\n        }\n\n        if (k instanceof Password) {\n            String msg = \"Passwords are intended for use with key derivation algorithms only.\";\n            throw new InvalidKeyException(msg);\n        }\n\n        final SecretKey key = (SecretKey) k;\n\n        final String id = getId();\n\n        assertAlgorithmName(key, signing);\n\n        int size = KeysBridge.findBitLength(key);\n\n        // We can only perform length validation if key bit length is available\n        // per https://github.com/jwtk/jjwt/issues/478 and https://github.com/jwtk/jjwt/issues/619\n        // so return early if we can't:","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/security/DefaultMacAlgorithm.java#L143-L179","documentation":"InvalidKeyException from DefaultMacAlgorithm.validateKey when the supplied Key is not a javax.crypto.SecretKey instance. MAC (HMAC) algorithms require symmetric secret keys, not RSA/EC public or private keys.","triggerScenarios":"Calling signWith(rsaPrivateKey, HS256) or verifyWith(ecPublicKey) with an HMAC algorithm; passing a java.security.Key from a keystore that is a PrivateKey.","commonSituations":"Mixing asymmetric signing code (RS256) with HMAC algorithm configuration; loading the wrong key entry from a keystore; copy-pasting algorithm constants while reusing key variables.","solutions":["Use a SecretKey: Keys.hmacShaKeyFor(secretBytes) or Jwts.SIG.HS256.key().build().","If you have an RSA/EC key pair, switch to the matching asymmetric algorithm (RS256/ES256) instead of HS256.","Check the keystore lookup so you retrieve the intended secret-key entry.","Guard with (key instanceof SecretKey) before calling signWith/verifyWith."],"exampleFix":"// before\nKeyPair kp = Keys.keyPairFor(SignatureAlgorithm.RS256);\nJwts.builder().signWith(kp.getPrivate(), Jwts.SIG.HS256); // wrong key type\n// after\nSecretKey key = Keys.hmacShaKeyFor(secretBytes);\nJwts.builder().signWith(key, Jwts.SIG.HS256);","handlingStrategy":"type-guard","validationCode":"static SecretKey requireSecretKey(Key k) {\n    if (!(k instanceof SecretKey))\n        throw new IllegalArgumentException(\"HMAC requires a SecretKey, got \" + k.getClass().getName());\n    return (SecretKey) k;\n}","typeGuard":"boolean isSecretKey(Key k) { return k instanceof javax.crypto.SecretKey; }","tryCatchPattern":"try {\n    return Jwts.builder().signWith(key, Jwts.SIG.HS256).compact();\n} catch (InvalidKeyException e) {\n    if (e.getMessage().contains(\"SecretKey instances\"))\n        throw new IllegalStateException(\"Asymmetric key used with MAC algorithm\");\n    throw e;\n}","preventionTips":["Pair algorithms and key types: HS* with SecretKey, RS*/PS*/ES* with KeyPair","Keystore lookups: confirm getEntry returns SecretKeyEntry, not PrivateKeyEntry","Keep separate typed fields for MAC keys vs signing key pairs"],"tags":["java","jjwt","type-mismatch","mac","hmac"],"backgroundTag":"type-mismatch","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"}