jwtk/jjwt · error · InvalidKeyException
Passwords are intended for use with key derivation algorithm
Error message
Passwords are intended for use with key derivation algorithms only.
What it means
InvalidKeyException from DefaultMacAlgorithm.validateKey when a jjwt Password instance is supplied to a MAC algorithm. Password objects are reserved for password-based key-derivation algorithms (e.g. PBES2) and must not be used directly as MAC keys.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/DefaultMacAlgorithm.java:166
}
@Override
protected void validateKey(Key k, boolean signing) {
final String keyType = keyType(signing);
if (k == null) {
throw new IllegalArgumentException("MAC " + keyType + " key cannot be null.");
}
if (!(k instanceof SecretKey)) {
String msg = "MAC " + keyType + " keys must be SecretKey instances. Specified key is of type " +
k.getClass().getName();
throw new InvalidKeyException(msg);
}
if (k instanceof Password) {
String msg = "Passwords are intended for use with key derivation algorithms only.";
throw new InvalidKeyException(msg);
}
final SecretKey key = (SecretKey) k;
final String id = getId();
assertAlgorithmName(key, signing);
int size = KeysBridge.findBitLength(key);
// We can only perform length validation if key bit length is available
// per https://github.com/jwtk/jjwt/issues/478 and https://github.com/jwtk/jjwt/issues/619
// so return early if we can't:
if (size < 0) return;
if (size < this.minKeyBitLength) {
String msg = "The " + keyType + " key's size is " + size + " bits which " +
"is not secure enough for the " + id + " algorithm.";View on GitHub (pinned to fb71496164)
Solutions
- Derive a real SecretKey from the password first, or use the PBES2 family (Jwts.SIG.PS256 with a password, or JWE PBES2 key algorithms).
- Convert the raw password bytes to a key: Keys.hmacShaKeyFor(derivedBytes).
- Pass a SecretKeySpec instead of a Password if you truly intend HMAC.
- Separate password handling (key derivation) from signing key handling in your code.
Example fix
// before Password pw = Jwts.password().of(chars); Jwts.builder().signWith(pw, Jwts.SIG.HS256); // after SecretKey key = Keys.hmacShaKeyFor(pw.getBytes()); // derived MAC key Jwts.builder().signWith(key, Jwts.SIG.HS256);
Defensive patterns
Strategy: type-guard
Validate before calling
static SecretKey requireNonPassword(Key k) {
if (k instanceof io.jsonwebtoken.security.Password)
throw new IllegalArgumentException("Use Password only with key-derivation algorithms; derive a SecretKey for MAC");
return (SecretKey) k;
} Type guard
boolean isPasswordKey(Key k) { return k instanceof io.jsonwebtoken.security.Password; } Try / catch
try {
return Jwts.builder().signWith(key, Jwts.SIG.HS256).compact();
} catch (InvalidKeyException e) {
if (e.getMessage().contains("key derivation algorithms only"))
throw new IllegalStateException("Password used directly as MAC key");
throw e;
} Prevention
- Keep Password objects confined to PBKDF2/PBES2 code paths
- Derive an explicit SecretKey (e.g. via hmacShaKeyFor) before MAC operations
- Document the distinction between 'password' and 'key' in your crypto helpers
When it happens
Trigger: Calling Jwts.builder().signWith(password, HS256) where password = Jwts.password().of(...) or io.jsonwebtoken.security.Password obtained for PBKDF2/PBES2 flows.
Common situations: Using the user password object everywhere after setting up PBES2 encryption; confusing 'secret string' keys with jjwt Password wrappers; following an outdated tutorial that wraps passwords as keys.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- derivedKeyBitLength may not exceed ${bitsMsg(MAX_DERIVED_KEY
- The ${keyType(signing)} key's algorithm cannot be null or em
- The ${keyType(signing)} key's algorithm '${name}' does not e
- MAC ${keyType} key cannot be null.
- MAC ${keyType} keys must be SecretKey instances. Specified
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/c4f8e4f05f3ee173.
Report an issue: GitHub.