jwtk/jjwt · error · MalformedKeyException
RSA JWK 'oth' (Other Prime Info) element cannot be null.
Error message
RSA JWK 'oth' (Other Prime Info) element cannot be null.
What it means
When converting an RSA JWK's 'oth' (Other Prime Info) array back into a java.security.spec.RSAOtherPrimeInfo, each element must be a non-null map of name/value pairs (r, d, t). A null element is rejected with MalformedKeyException.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/RSAOtherPrimeInfoConverter.java:53
static final Parameter<BigInteger> PRIME_FACTOR = Parameters.secretBigInt("r", "Prime Factor");
static final Parameter<BigInteger> FACTOR_CRT_EXPONENT = Parameters.secretBigInt("d", "Factor CRT Exponent");
static final Parameter<BigInteger> FACTOR_CRT_COEFFICIENT = Parameters.secretBigInt("t", "Factor CRT Coefficient");
static final Set<Parameter<?>> PARAMS = Collections.<Parameter<?>>setOf(PRIME_FACTOR, FACTOR_CRT_EXPONENT, FACTOR_CRT_COEFFICIENT);
@Override
public Object applyTo(RSAOtherPrimeInfo info) {
Map<String, Object> m = new LinkedHashMap<>(3);
m.put(PRIME_FACTOR.getId(), PRIME_FACTOR.applyTo(info.getPrime()));
m.put(FACTOR_CRT_EXPONENT.getId(), FACTOR_CRT_EXPONENT.applyTo(info.getExponent()));
m.put(FACTOR_CRT_COEFFICIENT.getId(), FACTOR_CRT_COEFFICIENT.applyTo(info.getCrtCoefficient()));
return m;
}
@Override
public RSAOtherPrimeInfo applyFrom(Object o) {
if (o == null) {
throw new MalformedKeyException("RSA JWK 'oth' (Other Prime Info) element cannot be null.");
}
if (!(o instanceof Map)) {
String msg = "RSA JWK 'oth' (Other Prime Info) must contain map elements of name/value pairs. " +
"Element type found: " + o.getClass().getName();
throw new MalformedKeyException(msg);
}
Map<?, ?> m = (Map<?, ?>) o;
if (Collections.isEmpty(m)) {
throw new MalformedKeyException("RSA JWK 'oth' (Other Prime Info) element map cannot be empty.");
}
// Need a Context instance to satisfy the API contract of the reader.get* methods below.
JwkContext<?> ctx = new DefaultJwkContext<>(PARAMS);
try {
for (Map.Entry<?, ?> entry : m.entrySet()) {
String name = String.valueOf(entry.getKey());
ctx.put(name, entry.getValue());
}View on GitHub (pinned to fb71496164)
Solutions
- Remove null entries from the 'oth' array, or omit 'oth' entirely for standard two-prime RSA keys.
- Sanitize/validate the JWK JSON before parsing, rejecting null array elements.
- Catch MalformedKeyException when ingesting external JWKs and treat the key as invalid.
Example fix
// before
{"kty":"RSA","oth":[null]}
// after
{"kty":"RSA"} // or a fully populated oth element
{"kty":"RSA","oth":[{"r":"...","d":"...","t":"..."}]} Defensive patterns
Strategy: validation
Validate before calling
List<Object> oth = jwk.get("oth", List.class);
if (oth != null) {
oth.forEach(e -> Objects.requireNonNull(e, "oth element must not be null"));
} Type guard
boolean validOth(List<Object> oth) {
return oth == null || oth.stream().allMatch(e -> e instanceof Map && e != null);
} Try / catch
try {
RsaJwk jwk = Jwks.parser().build().parse(json);
} catch (MalformedKeyException e) {
// malformed oth (or other) JWK field
} Prevention
- Omit 'oth' for standard two-prime RSA keys
- Sanitize third-party JWK JSON before parsing
- Never emit null placeholders in JWK arrays
When it happens
Trigger: Parsing an RSA JWK whose 'oth' array contains a JSON null element, e.g. {"oth":[null]} or building a JWK with a null entry in the oth collection.
Common situations: Hand-edited or third-party-generated JWKs with null placeholders; serializers emitting nulls for missing primes instead of omitting the 'oth' parameter.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- JWK is missing required kty parameter.
- JWK kty value cannot be null.
- JWK kty value cannot be empty.
- ${name()} is missing required ${param} value.
- Unrelated key operations are not allowed. KeyOperation [${in
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/98d8d5fd5836e462.
Report an issue: GitHub.