jwtk/jjwt · error · IllegalArgumentException
Invalid AES key length: ${bitsMsg(keyBitLength)}. AES only s
Error message
Invalid AES key length: ${bitsMsg(keyBitLength)}. AES only supports 128, 192, or 256 bit keys. What it means
AesAlgorithm.assertKeyBitLength enforces AES-compliant key sizes: exactly 128, 192, or 256 bits. Any other length throws IllegalArgumentException with a human-readable bits message. It is called by keyFor and the constructor, so malformed AES key bytes are rejected early.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/AesAlgorithm.java:68
"requests that do not include initialization vectors. AES ciphertext without an IV is weak and " +
"susceptible to attack.";
protected final int keyBitLength;
protected final int ivBitLength;
protected final int tagBitLength;
protected final boolean gcm;
/**
* Ensures {@code keyBitLength is a valid AES key length}
*
* @param keyBitLength the key length (in bits) to check
* @since 0.12.4
*/
static void assertKeyBitLength(int keyBitLength) {
if (keyBitLength == 128 || keyBitLength == 192 || keyBitLength == 256) return; // valid
String msg = "Invalid AES key length: " + Bytes.bitsMsg(keyBitLength) + ". AES only supports " +
"128, 192, or 256 bit keys.";
throw new IllegalArgumentException(msg);
}
static SecretKey keyFor(byte[] bytes) {
int bitlen = (int) Bytes.bitLength(bytes);
assertKeyBitLength(bitlen);
return new SecretKeySpec(bytes, KEY_ALG_NAME);
}
AesAlgorithm(String id, final String jcaTransformation, int keyBitLength) {
super(id, jcaTransformation);
assertKeyBitLength(keyBitLength);
this.keyBitLength = keyBitLength;
this.gcm = jcaTransformation.startsWith("AES/GCM");
this.ivBitLength = jcaTransformation.equals("AESWrap") ? 0 : (this.gcm ? GCM_IV_SIZE : BLOCK_SIZE);
// https://tools.ietf.org/html/rfc7518#section-5.2.3 through https://tools.ietf.org/html/rfc7518#section-5.3 :
this.tagBitLength = this.gcm ? BLOCK_SIZE : this.keyBitLength;
}
View on GitHub (pinned to fb71496164)
Solutions
- Derive a proper AES key from a password with PBKDF2: SecretKeyFactory.getInstance('PBKDF2WithHmacSHA256') then pad/choose 256-bit output.
- Generate keys with KeyGenerator.getInstance("AES") initialized to 128/192/256 bits.
- Check bytes.length * 8 is 128, 192, or 256 before calling keyFor.
- Trim stray whitespace/newlines from encoded key strings before decoding.
Example fix
// before
SecretKey key = Keys.forAes(password.getBytes());
// after
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256);
SecretKey key = kg.generateKey(); Defensive patterns
Strategy: validation
Validate before calling
if (bytes.length * 8 != 128 && bytes.length * 8 != 192 && bytes.length * 8 != 256) throw new IllegalArgumentException("AES key must be 128/192/256 bits, got " + bytes.length * 8); Type guard
boolean isAesKeyLength(byte[] b) { int bits = b.length * 8; return bits == 128 || bits == 192 || bits == 256; } Try / catch
try { SecretKey k = Keys.forAes(bytes); }
catch (IllegalArgumentException e) { throw new ConfigException("Bad AES key material: " + e.getMessage()); } Prevention
- Generate AES keys with KeyGenerator.getInstance("AES").
- Derive keys from passwords with PBKDF2, never raw passwords.
- Strip whitespace before base64-decoding key material.
- Assert key byte length in unit tests.
When it happens
Trigger: Calling KeysBuilder/SecretKeySpec-style AES key creation with byte arrays whose bit length is not 128/192/256 (e.g. a 16-byte string plus newline = 136 bits, truncated base64, or a password used directly as key bytes).
Common situations: Using a raw password as an AES key; decoding base64 keys with whitespace; generating keys with a non-AES KeyGenerator; hand-truncating key material.
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 compute ${getId()} signature with JCA algorithm '$
- The '${id}' algorithm requires keys with a length of ${bitsM
- Unexpected unsecured Claims JWT.
- Unexpected content JWS.
- Unexpected Claims JWS.
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/612a0faed7b1c423.
Report an issue: GitHub.