jwtk/jjwt · critical · WeakKeyException
The specified key byte array is bits which is not secure en
Error message
The specified key byte array is bits which is not secure enough for any JWT HMAC-SHA algorithm. The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with HMAC-SHA algorithms MUST have a size >= 256 bits (the key size must be greater than or equal to the hash output size). Consider using the Jwts.SIG.HS256.key() builder (or HS384.key() or HS512.key()) to create a key guaranteed to be secure enough for your preferred HMAC-SHA algorithm. See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.
What it means
Keys.hmacShaKeyFor throws WeakKeyException when the supplied key byte array is shorter than 256 bits (32 bytes), which RFC 7518 §3.2 forbids for JWT HMAC-SHA algorithms. This is a deliberate security guard — weak keys make MAC forgery feasible.
Source
Thrown at api/src/main/java/io/jsonwebtoken/security/Keys.java:83
int bitLength = bytes.length * 8;
//Purposefully ordered higher to lower to ensure the strongest key possible can be generated.
if (bitLength >= 512) {
return new SecretKeySpec(bytes, "HmacSHA512");
} else if (bitLength >= 384) {
return new SecretKeySpec(bytes, "HmacSHA384");
} else if (bitLength >= 256) {
return new SecretKeySpec(bytes, "HmacSHA256");
}
String msg = "The specified key byte array is " + bitLength + " bits which " +
"is not secure enough for any JWT HMAC-SHA algorithm. The JWT " +
"JWA Specification (RFC 7518, Section 3.2) states that keys used with HMAC-SHA algorithms MUST have a " +
"size >= 256 bits (the key size must be greater than or equal to the hash " +
"output size). Consider using the Jwts.SIG.HS256.key() builder (or HS384.key() " +
"or HS512.key()) to create a key guaranteed to be secure enough for your preferred HMAC-SHA " +
"algorithm. See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.";
throw new WeakKeyException(msg);
}
/**
* <p><b>Deprecation Notice</b></p>
*
* <p>As of JJWT 0.12.0, symmetric (secret) key algorithm instances can generate a key of suitable
* length for that specific algorithm by calling their {@code key()} builder method directly. For example:</p>
*
* <pre><code>
* {@link Jwts.SIG#HS256}.key().build();
* {@link Jwts.SIG#HS384}.key().build();
* {@link Jwts.SIG#HS512}.key().build();
* </code></pre>
*
* <p>Call those methods as needed instead of this static {@code secretKeyFor} helper method - the returned
* {@link KeyBuilder} allows callers to specify a preferred Provider or SecureRandom on the builder if
* desired, whereas this {@code secretKeyFor} method does not. Consequently this helper method will be removed
* before the 1.0 release.</p>View on GitHub (pinned to fb71496164)
Solutions
- Generate a key of at least 256 bits: Keys.secretKeyFor(SignatureAlgorithm.HS256) or Jwts.SIG.HS256.key().build()
- Use a random secret of >= 32 bytes, e.g. Base64 of 32+ random bytes
- Verify key length before calling: if (bytes.length < 32) fail at startup
- Persist the generated strong key securely (secret manager, vault) rather than a short string
Example fix
// before
SecretKey key = Keys.hmacShaKeyFor("secret".getBytes()); // WeakKeyException
// after
SecretKey key = Keys.secretKeyFor(io.jsonwebtoken.SignatureAlgorithm.HS256);
String encoded = Base64.getEncoder().encodeToString(key.getEncoded()); // store securely Defensive patterns
Strategy: validation
Validate before calling
if (secretBytes == null || secretBytes.length < 32) {
throw new IllegalStateException("JWT HMAC secret must be at least 256 bits (32 bytes)");
} Try / catch
try {
key = Keys.hmacShaKeyFor(secretBytes);
} catch (WeakKeyException e) {
throw new IllegalStateException("Refusing weak JWT secret; generate with Keys.secretKeyFor(HS256)", e);
} Prevention
- Generate secrets with Keys.secretKeyFor(SignatureAlgorithm.HS256) or a CSPRNG of >= 32 bytes
- Never use passwords, names, or short literals as HMAC secrets
- Store generated keys in a secret manager and rotate securely
- Add a startup length check so weak keys fail before serving traffic
When it happens
Trigger: Calling Keys.hmacShaKeyFor(bytes) where bytes.length * 8 < 512 bits fails the strongest checks and anything below 256 bits triggers this error — practically, passing a secret shorter than 32 bytes (e.g. "mysecret", a short password, or a truncated Base64 blob).
Common situations: Using a human-readable password as the JWT secret, hard-coded short demo secrets in production, or an env var silently cut off / partially loaded.
Related errors
- The ${keyType} key's size is ${size} bits which is not secur
- The RSA ${keyType} key size (aka modulus bit length) is ${si
- 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
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/93c6286c099513b0.
Report an issue: GitHub.