jwtk/jjwt · error · MalformedKeyException
Invalid Secret JWK value ' '. Secret JWKs may only be used…
Error message
Invalid Secret JWK ${AbstractJwk.ALG} value '${alg.getId()}'. Secret JWKs may only be used with symmetric (secret) key algorithms. What it means
Thrown as MalformedKeyException when a SecretJwk declares an 'alg' that is not a symmetric algorithm (MAC, secret-key encryption, or AEAD). Secret JWKs represent symmetric key material and can only be associated with symmetric algorithms.
Solutions
- Set 'alg' to a symmetric algorithm (HS256/HS384/HS512, AxxxKW key-wrap, or GCM AEAD algorithms).
- If the key is asymmetric, build the correct JWK type (EC or RSA JWK) instead of a SecretJwk.
- Validate the alg value against Jwts.SIG / Jwts.ENC registry before building the JWK.
Example fix
// before
values.put("kty", "oct");
values.put("alg", "RS256"); // asymmetric alg on secret JWK
// after
values.put("kty", "oct");
values.put("alg", "HS256"); Defensive patterns
Strategy: validation
Validate before calling
Object alg = Jwts.SIG.get().forId(algId);
if (!(alg instanceof MacAlgorithm || alg instanceof SecretKeyAlgorithm || alg instanceof AeadAlgorithm)) throw new IllegalStateException("Secret JWK needs a symmetric alg"); Type guard
boolean symmetricAlg(Object a) { return a instanceof MacAlgorithm || a instanceof SecretKeyAlgorithm || a instanceof AeadAlgorithm; } Try / catch
try { /* build SecretJwk */ } catch (MalformedKeyException e) { throw new IllegalArgumentException("Use HS*/A*KW/GCM algs for oct (secret) JWKs", e); } Prevention
- For kty=oct JWKs, only set alg to symmetric algorithms (HS256/384/512, AxxxKW, GCM).
- Use asymmetric JWK types (RSA/EC) for RSA/EC algorithms.
- Look up algorithms from Jwts.SIG/Jwts.ENC instead of hardcoding strings.
When it happens
Trigger: Building a SecretJwk from values with 'alg' set to an asymmetric algorithm such as RS256, ES256, or RSA-OAEP instead of HS256/A128KW/A256GCM etc.
Common situations: Copy-pasting JWK templates across key types; misconfiguring algorithm headers after switching key material; typos or mixing up JWK 'kty' (oct) with 'alg' families.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- ${e.getMessage()}
- RSA JWK 'oth' (Other Prime Info) element map cannot be…
- RSA JWK 'oth' (Other Prime Info) must contain map elements…
- Secret JWK value is ' ', but the length is smaller than the…
- Unable to create JWK
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/2bb64be992636602.
Report an issue: GitHub.
Appendix: source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/SecretJwkFactory.java:95
// 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();
if (!Strings.hasText(algId)) { // optional per https://www.rfc-editor.org/rfc/rfc7517.html#section-4.4
// Here we try to infer the best type of key to create based on siguse and/or key length.
//
// AES requires 128, 192, or 256 bits, so anything larger than 256 cannot be AES, so we'll need to assume
// HMAC.
//
// Also, 256 bits works for either HMAC or AES, so we just have to choose one as there is no other
// RFC-based criteria for determining. Historically, we've chosen AES due to the larger number ofView on GitHub (pinned to fb71496164)