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

  1. Derive a proper AES key from a password with PBKDF2: SecretKeyFactory.getInstance('PBKDF2WithHmacSHA256') then pad/choose 256-bit output.
  2. Generate keys with KeyGenerator.getInstance("AES") initialized to 128/192/256 bits.
  3. Check bytes.length * 8 is 128, 192, or 256 before calling keyFor.
  4. 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

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


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/612a0faed7b1c423. Report an issue: GitHub.