jwtk/jjwt · error · InvalidKeyException
JWS verification key must be either a SecretKey (for MAC alg
Error message
JWS verification key must be either a SecretKey (for MAC algorithms) or a PublicKey (for Signature algorithms).
What it means
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(...).
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java:264
}
@Override
public JwtParserBuilder setSigningKey(String base64EncodedSecretKey) {
Assert.hasText(base64EncodedSecretKey, "signature verification key cannot be null or empty.");
byte[] bytes = Decoders.BASE64.decode(base64EncodedSecretKey);
return setSigningKey(bytes);
}
@Override
public JwtParserBuilder setSigningKey(final Key key) {
if (key instanceof SecretKey) {
return verifyWith((SecretKey) key);
} else if (key instanceof PublicKey) {
return verifyWith((PublicKey) key);
}
String msg = "JWS verification key must be either a SecretKey (for MAC algorithms) or a PublicKey " +
"(for Signature algorithms).";
throw new InvalidKeyException(msg);
}
@Override
public JwtParserBuilder verifyWith(SecretKey key) {
return verifyWith((Key) key);
}
@Override
public JwtParserBuilder verifyWith(PublicKey key) {
return verifyWith((Key) key);
}
private JwtParserBuilder verifyWith(Key key) {
if (key instanceof PrivateKey) {
throw new IllegalArgumentException(DefaultJwtParser.PRIV_KEY_VERIFY_MSG);
}
this.signatureVerificationKey = Assert.notNull(key, "signature verification key cannot be null.");
return this;View on GitHub (pinned to fb71496164)
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.
Example fix
// before PrivateKey privateKey = loadPrivateKey(); Jwts.parser().setSigningKey(privateKey).build().parse(jwt); // InvalidKeyException // after PublicKey publicKey = loadPublicKey(); // matching public key Jwts.parser().verifyWith(publicKey).build().parse(jwt); // or for MAC: Jwts.parser().verifyWith(new SecretKeySpec(secretBytes, "HmacSHA256")).build()
Defensive patterns
Strategy: type-guard
Validate before calling
boolean isUsableVerificationKey(java.security.Key k) {
return k instanceof javax.crypto.SecretKey || k instanceof java.security.PublicKey;
}
if (!isUsableVerificationKey(key)) throw new IllegalArgumentException("Need SecretKey or PublicKey"); Type guard
boolean isVerificationKey(java.security.Key k) {
return k instanceof javax.crypto.SecretKey || k instanceof java.security.PublicKey;
} Try / catch
try {
parserBuilder.setSigningKey(key);
} catch (io.jsonwebtoken.security.InvalidKeyException e) {
// wrong key type: select PublicKey for RSA/EC tokens or SecretKeySpec for MAC
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unable to determine JWA-standard Elliptic Curve for ${type}k
- PrivateKeys may not be used to verify digital signatures. Pr
- PrivateKeys may not be used to verify digital signatures. Pr
- PublicKeys may not be used to decrypt data. PublicKeys are u
- The provided Elliptic Curve ${keyType} key size (aka order b
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/c597aab87beddf5b.
Report an issue: GitHub.