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
- Generate a compliant key: Jwts.SIG.HS256.key().build() (or Keys.secretKeyFor(MacAlgorithm)).
- Use Keys.hmacShaKeyFor(bytes) which enforces/normalizes size; give it >= 32 bytes for HS256.
- Store a longer base64 secret in config and decode all of it; never truncate.
- 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
- Generate keys with Jwts.SIG.HS256.key().build(); never embed short string secrets
- Ensure configured secrets decode to >= 32 bytes (HS256) / 48 (HS384) / 64 (HS512)
- Test key length in CI with an assertion per environment config
- If upgrading from old weak secrets, plan a key-rotation window where both keys verify
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
- The specified key byte array is bits which is not secure en
- SecretKey byte array cannot be null.
- The '${id}' algorithm requires keys with a length of ${bitsM
- The ${keyType(signing)} key's algorithm cannot be null or em
- The ${keyType(signing)} key's algorithm '${name}' does not e
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/55f4760af5ec77de.
Report an issue: GitHub.