{"record":{"id":"cd6b2fafb9d3a528","repo":"gchq/CyberChef","slug":"invalid-jwk-format","errorCode":null,"errorMessage":"Invalid JWK format","messagePattern":"Invalid JWK format","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/JWKToPem.mjs","lineNumber":64,"sourceCode":"        let keys = [];\n        if (Array.isArray(inputJson)) {\n            // list of keys => transform all keys\n            keys = inputJson;\n        } else if (Array.isArray(inputJson.keys)) {\n            // JSON Web Key Set => transform all keys\n            keys = inputJson.keys;\n        } else if (typeof inputJson === \"object\") {\n            // single key\n            keys.push(inputJson);\n        } else {\n            throw new OperationError(\"Input is not a JSON Web Key\");\n        }\n\n        let output = \"\";\n        for (let i=0; i<keys.length; i++) {\n            const jwk = keys[i];\n            if (typeof jwk.kty !== \"string\") {\n                throw new OperationError(\"Invalid JWK format\");\n            } else if (\"|RSA|EC|\".indexOf(jwk.kty) === -1) {\n                throw new OperationError(`Unsupported JWK key type '${inputJson.kty}'`);\n            }\n\n            const key = r.KEYUTIL.getKey(jwk);\n            const pem = key.isPrivate ? r.KEYUTIL.getPEM(key, \"PKCS8PRV\") : r.KEYUTIL.getPEM(key);\n\n            // PEM ends with '\\n', so a new key always starts on a new line\n            output += pem;\n        }\n\n        return output;\n    }\n}\n\nexport default PEMToJWK;\n","sourceCodeStart":46,"sourceCodeEnd":81,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/JWKToPem.mjs#L46-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-building a JWK and forgetting kty. Receiving a partial/corrupt key from an API. Mixing key parameter sets that lack the type discriminator.","solutions":["Ensure every key object includes kty as a string (e.g. 'RSA' or 'EC').","Filter the keys array to drop entries without a valid string kty before conversion.","Round-trip through a key validator or re-export the key from its PEM/DER form."],"exampleFix":"// before: missing kty\nchef.JWKToPem(JSON.stringify({ n: '...', e: 'AQAB' }));\n// after: kty declared\nchef.JWKToPem(JSON.stringify({ kty: 'RSA', n: '...', e: 'AQAB' }));","handlingStrategy":"validation","validationCode":"function ensureKty(keys) {\n  const arr = Array.isArray(keys) ? keys : [keys];\n  arr.forEach(k => {\n    if (!k || typeof k.kty !== 'string') throw new Error('Each key needs a string kty field');\n  });\n  return arr;\n}","typeGuard":"function hasStringKty(jwk) {\n  return jwk !== null && typeof jwk === 'object' && typeof jwk.kty === 'string';\n}","tryCatchPattern":"try {\n  return chef.JWKToPem(input);\n} catch (e) {\n  if (/Invalid JWK format/.test(e.message)) throw new Error('Add a string kty (e.g. RSA/EC) to each key');\n  throw e;\n}","preventionTips":["Always include kty on every JWK.","Filter key sets to entries with a valid string kty first.","Re-export keys from PEM/DER if kty is missing."],"tags":["jwk","crypto","key","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}