jwtk/jjwt · error · WeakKeyException

Secret JWK value is ' ', but the length is smaller than the…

Error message

Secret JWK ${AbstractJwk.ALG} value is '${alg.getId()}', but the ${DefaultSecretJwk.K} length is smaller than the ${alg.getId()} minimum length of ${Bytes.bitsMsg(requiredBitLen)} required by [JWA RFC 7518, Section 3.2](https://www.rfc-editor.org/rfc/rfc7518.html#section-3.2), 2nd paragraph: 'A key of the same size as the hash output or larger MUST be used with this algorithm.'

What it means

Thrown as WeakKeyException when creating a SecretJwk whose 'alg' identifies a MAC algorithm, but the Base64URL-decoded 'k' key material is shorter than the algorithm's minimum bit length required by RFC 7518 Section 3.2 ('A key of the same size as the hash output or larger MUST be used').

Solutions

  1. Generate a longer key: at least the hash output size of the declared algorithm (32 bytes for HS256, 48 for HS384, 64 for HS512).
  2. Or change the JWK 'alg' to match the actual key strength (e.g. HS256 for a 256-bit key).
  3. Use Keys.secretKeyFor(SignatureAlgorithm) / Jwts.SIG.HSxxx.key().build() to guarantee correct size.

Example fix

// before
SecretKey key = new SecretKeySpec("short-secret".getBytes(), "HmacSHA512"); // < 512 bits
// after
SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS512); // 512-bit key
Defensive patterns

Strategy: validation

Validate before calling

int minBytes = "HS512".equals(alg) ? 64 : "HS384".equals(alg) ? 48 : 32; // HS256
if (secretKey.getEncoded().length < minBytes) throw new IllegalStateException("Key too short for " + alg);

Type guard

boolean keyFitsAlg(SecretKey k, MacAlgorithm alg) { return k.getEncoded() != null && k.getEncoded().length * 8 >= alg.getKeyBitLength(); }

Try / catch

try { /* build SecretJwk */ } catch (WeakKeyException e) { throw new IllegalStateException("Regenerate key with Jwts.SIG." + algId + ".key().build()", e); }

Prevention

When it happens

Trigger: Building a SecretJwk from values with a short 'k' (e.g. a 128-bit key) while 'alg' is set to HS256/HS384/HS512 (minimums 256/384/512 bits).

Common situations: Hand-rolled JWKs with truncated secrets; test secrets reused for strong algorithms; keys generated for HS256 then declared as HS512 after an algorithm upgrade.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/SecretJwkFactory.java:86

        ctx.put(DefaultSecretJwk.K.getId(), k);

        return createJwkFromValues(ctx);
    }

    private static void assertKeyBitLength(byte[] bytes, MacAlgorithm alg) {
        long bitLen = Bytes.bitLength(bytes);
        long requiredBitLen = alg.getKeyBitLength();
        if (bitLen < requiredBitLen) {
            // Implementors note:  Don't print out any information about the `bytes` value itself - size,
            // content, etc., as it is considered secret material:
            String msg = "Secret JWK " + AbstractJwk.ALG + " value is '" + alg.getId() +
                    "', but the " + DefaultSecretJwk.K + " length is smaller than the " + alg.getId() +
                    " minimum length of " + Bytes.bitsMsg(requiredBitLen) +
                    " required by " +
                    "[JWA RFC 7518, Section 3.2](https://www.rfc-editor.org/rfc/rfc7518.html#section-3.2), " +
                    "2nd paragraph: 'A key of the same size as the hash output or larger MUST be used with this " +
                    "algorithm.'";
            throw new WeakKeyException(msg);
        }
    }

    private static void assertSymmetric(Identifiable alg) {
        if (alg instanceof MacAlgorithm || alg instanceof SecretKeyAlgorithm || alg instanceof AeadAlgorithm)
            return; // valid
        String msg = "Invalid Secret JWK " + AbstractJwk.ALG + " value '" + alg.getId() + "'. Secret JWKs " +
                "may only be used with symmetric (secret) key algorithms.";
        throw new MalformedKeyException(msg);
    }

    @Override
    protected SecretJwk createJwkFromValues(JwkContext<SecretKey> ctx) {
        ParameterReadable reader = new RequiredParameterReader(ctx);
        final byte[] bytes = reader.get(DefaultSecretJwk.K);
        SecretKey key;

        String algId = ctx.getAlgorithm();

View on GitHub (pinned to fb71496164)