gchq/CyberChef · error · OperationError

Invalid JWK format

Error message

Invalid JWK format

What it means

Thrown during JWK to PEM iteration when an individual key's 'kty' (key type) field is absent or not a string. Every JWK must declare kty as a string so the key library can dispatch to the correct algorithm; a missing or mistyped kty is treated as a malformed key.

Source

Thrown at src/core/operations/JWKToPem.mjs:64

        let keys = [];
        if (Array.isArray(inputJson)) {
            // list of keys => transform all keys
            keys = inputJson;
        } else if (Array.isArray(inputJson.keys)) {
            // JSON Web Key Set => transform all keys
            keys = inputJson.keys;
        } else if (typeof inputJson === "object") {
            // single key
            keys.push(inputJson);
        } else {
            throw new OperationError("Input is not a JSON Web Key");
        }

        let output = "";
        for (let i=0; i<keys.length; i++) {
            const jwk = keys[i];
            if (typeof jwk.kty !== "string") {
                throw new OperationError("Invalid JWK format");
            } else if ("|RSA|EC|".indexOf(jwk.kty) === -1) {
                throw new OperationError(`Unsupported JWK key type '${inputJson.kty}'`);
            }

            const key = r.KEYUTIL.getKey(jwk);
            const pem = key.isPrivate ? r.KEYUTIL.getPEM(key, "PKCS8PRV") : r.KEYUTIL.getPEM(key);

            // PEM ends with '\n', so a new key always starts on a new line
            output += pem;
        }

        return output;
    }
}

export default PEMToJWK;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Ensure every key object includes kty as a string (e.g. 'RSA' or 'EC').
  2. Filter the keys array to drop entries without a valid string kty before conversion.
  3. Round-trip through a key validator or re-export the key from its PEM/DER form.

Example fix

// before: missing kty
chef.JWKToPem(JSON.stringify({ n: '...', e: 'AQAB' }));
// after: kty declared
chef.JWKToPem(JSON.stringify({ kty: 'RSA', n: '...', e: 'AQAB' }));
Defensive patterns

Strategy: validation

Validate before calling

function ensureKty(keys) {
  const arr = Array.isArray(keys) ? keys : [keys];
  arr.forEach(k => {
    if (!k || typeof k.kty !== 'string') throw new Error('Each key needs a string kty field');
  });
  return arr;
}

Type guard

function hasStringKty(jwk) {
  return jwk !== null && typeof jwk === 'object' && typeof jwk.kty === 'string';
}

Try / catch

try {
  return chef.JWKToPem(input);
} catch (e) {
  if (/Invalid JWK format/.test(e.message)) throw new Error('Add a string kty (e.g. RSA/EC) to each key');
  throw e;
}

Prevention

When it happens

Trigger: A key object that omits 'kty' entirely. A key where 'kty' is a number, object, array, or null. A JWKS whose entries are incomplete placeholders.

Common situations: Hand-building a JWK and forgetting kty. Receiving a partial/corrupt key from an API. Mixing key parameter sets that lack the type discriminator.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/cd6b2fafb9d3a528. Report an issue: GitHub.