jwtk/jjwt · error · WeakKeyException
The '${id}' algorithm requires keys with a length of ${bitsM
Error message
The '${id}' algorithm requires keys with a length of ${bitsMsg(requiredLengthInBits)}. The provided key has a length of ${bitsMsg(keyBitLength)}. What it means
Thrown as a WeakKeyException by AesAlgorithm.validateLength (via encoded) when an AES key supplied to a JWE encryption algorithm (A128GCM, A256GCM-KW, etc.) is shorter than the required bit length. The library refuses to use cryptographically weak keys rather than silently producing insecure output.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/AesAlgorithm.java:128
Bytes.bitsMsg(requiredLengthInBits) + ". The provided key has a length of " +
Bytes.bitsMsg(actualLengthInBits) + ".";
}
protected byte[] validateLength(SecretKey key, int requiredBitLength, boolean propagate) {
byte[] keyBytes;
try {
keyBytes = key.getEncoded();
} catch (RuntimeException re) {
if (propagate) {
throw re;
}
//can't get the bytes to validate, e.g. hardware security module or later Android, so just return:
return null;
}
long keyBitLength = Bytes.bitLength(keyBytes);
if (keyBitLength < requiredBitLength) {
throw new WeakKeyException(lengthMsg(getId(), "keys", requiredBitLength, keyBitLength));
}
return keyBytes;
}
protected byte[] assertBytes(byte[] bytes, String type, int requiredBitLen) {
long bitLen = Bytes.bitLength(bytes);
if (requiredBitLen != bitLen) {
String msg = lengthMsg(getId(), type, requiredBitLen, bitLen);
throw new IllegalArgumentException(msg);
}
return bytes;
}
byte[] assertIvLength(final byte[] iv) {
return assertBytes(iv, "initialization vectors", this.ivBitLength);
}
View on GitHub (pinned to fb71496164)
Solutions
- Generate a correctly sized key: Jwts.SIG.A256GCM.key().build() or SecretKey with 32 bytes for AES-256.
- If deriving bytes from a secret string, hash them (e.g. SHA-256) to reach the required length.
- Verify the encoded key length before use: Bytes.bitLength or key.getEncoded().length * 8.
- Use KeysBridge/password-based derivation (jwe key encryption) to derive a correctly sized content key.
Example fix
// before SecretKey key = new SecretKeySpec(new byte[16], "AES"); // 128 bits Jwts.builder().encryptWith(key, Jwts.SIG.A256GCM, alg).compact(); // after SecretKey key = Jwts.SIG.A256GCM.key().build(); // 256 bits Jwts.builder().encryptWith(key, Jwts.SIG.A256GCM, alg).compact();
Defensive patterns
Strategy: validation
Validate before calling
static boolean isAesKeyLongEnough(SecretKey key, int requiredBits) {
return key != null && key.getEncoded() != null
&& key.getEncoded().length * 8 >= requiredBits;
}
if (!isAesKeyLongEnough(key, 256)) throw new IllegalArgumentException("A256GCM needs a 256-bit key"); Type guard
boolean isAesKey(Key k) { return k instanceof SecretKey && "AES".equals(((SecretKey) k).getAlgorithm()); } Try / catch
try {
Jwts.builder().encryptWith(key, Jwts.SIG.A256GCM, alg).compact();
} catch (WeakKeyException e) {
logger.error("AES key too small: {}", e.getMessage());
key = Jwts.SIG.A256GCM.key().build();
} Prevention
- Always generate keys with Jwts.SIG.<alg>.key().build() instead of hand-rolling byte arrays
- Log key size (never the key) at startup to verify configuration
- Store secrets base64-encoded at full required length
- Write a unit test asserting encoded key bit length per algorithm
When it happens
Trigger: Calling Jwts.builder().encryptWith(key, alg) or Jwts.parser().decryptWith(key) where key.getEncoded().length*8 < requiredBitLength (e.g. a 128-bit key with A256GCM).
Common situations: Generating a key with KeyGenerator without setting the key size (defaults to 128 bits); loading a truncated or Base64-decoded secret that is shorter than expected; hard-coding a short demo secret then switching to a 256-bit algorithm.
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
- Unexpected content JWE.
- Unexpected Claims JWE.
- The specified key byte array is bits which is not secure en
- The '${id}' algorithm requires ${type} with a length of ${bi
- derivedKeyBitLength may not exceed ${bitsMsg(MAX_DERIVED_KEY
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/3ba3c6906bb9ceb7.
Report an issue: GitHub.