jwtk/jjwt · error · WeakKeyException

The ${keyType} key's size is ${size} bits which is not secur

Error message

The ${keyType} key's size is ${size} bits which is not secure enough for the ${id} algorithm. The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with ${id} MUST have a size >= ${minKeyBitLength} bits (the key size must be greater than or equal to the hash output size). Consider using the Jwts.SIG.${id}.key() builder to create a key guaranteed to be secure enough for ${id}.  See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.

What it means

WeakKeyException from DefaultMacAlgorithm.validateKey when an HMAC key is shorter than the hash output size required by RFC 7518 Section 3.2 (e.g. HS256 needs >= 256-bit keys). For standard algorithms the message references the JWA spec and suggests the Jwts.SIG key builders; custom algorithms get a simpler message.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/DefaultMacAlgorithm.java:197

        // 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.";

            if (isJwaStandard() && isJwaStandardJcaName(getJcaName())) { //JWA standard algorithm name - reference the spec:
                msg += " The JWT " +
                        "JWA Specification (RFC 7518, Section 3.2) states that keys used with " + id + " MUST have a " +
                        "size >= " + minKeyBitLength + " bits (the key size must be greater than or equal to the hash " +
                        "output size). Consider using the Jwts.SIG." + id + ".key() " +
                        "builder to create a key guaranteed to be secure enough for " + id + ".  See " +
                        "https://tools.ietf.org/html/rfc7518#section-3.2 for more information.";
            } else { //custom algorithm - just indicate required key length:
                msg += " The " + id + " algorithm requires keys to have a size >= " + minKeyBitLength + " bits.";
            }

            throw new WeakKeyException(msg);
        }
    }

    @Override
    public byte[] doDigest(final SecureRequest<InputStream, SecretKey> request) {
        return jca(request).withMac(new CheckedFunction<Mac, byte[]>() {
            @Override
            public byte[] apply(Mac mac) throws Exception {
                mac.init(request.getKey());
                InputStream payload = request.getPayload();
                byte[] buf = new byte[1024];
                int len = 0;
                while (len != -1) {
                    len = payload.read(buf);
                    if (len > 0) mac.update(buf, 0, len);
                }
                return mac.doFinal();
            }

View on GitHub (pinned to fb71496164)

Solutions

  1. Generate a compliant key: Jwts.SIG.HS256.key().build() (or Keys.secretKeyFor(MacAlgorithm)).
  2. Use Keys.hmacShaKeyFor(bytes) which enforces/normalizes size; give it >= 32 bytes for HS256.
  3. Store a longer base64 secret in config and decode all of it; never truncate.
  4. If the key genuinely must stay small, downgrade the algorithm (HS256->smaller hash is not allowed; use a custom algorithm acknowledging the risk) - preferred is to upgrade the key.

Example fix

// before
SecretKey key = Keys.hmacShaKeyFor("secret".getBytes()); // 48 bits - too weak
Jwts.builder().signWith(key, Jwts.SIG.HS256);
// after
SecretKey key = Jwts.SIG.HS256.key().build(); // 256-bit key
Jwts.builder().signWith(key, Jwts.SIG.HS256);
Defensive patterns

Strategy: validation

Validate before calling

static SecretKey strongHmacKey(byte[] secret, int minBits) {
    if (secret.length * 8 < minBits)
        throw new IllegalArgumentException("Secret too short: need >= " + minBits + " bits for this MAC algorithm");
    return Keys.hmacShaKeyFor(secret);
}
// strongHmacKey(secret, 256) before HS256

Try / catch

try {
    return Jwts.builder().signWith(key, Jwts.SIG.HS256).compact();
} catch (WeakKeyException e) {
    logger.error("HMAC key below RFC 7518 3.2 minimum; generate a new key");
    throw e; // do NOT silently replace: tokens signed with a new key won't verify
}

Prevention

When it happens

Trigger: signWith/verifyWith HS256 with a key under 32 bytes (256 bits); a short string secret converted directly via getBytes(); keys generated with KeyGenerator without setting key size.

Common situations: Hard-coded short secrets like 'secret' or 'mykey' in demos/config; legacy systems built before jjwt 0.10 (which relaxed then re-enforced RFC minimums); keys migrated between environments and truncated.

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/55f4760af5ec77de. Report an issue: GitHub.