gchq/CyberChef · error · OperationError

PEM footer '${footer}' not found

Error message

PEM footer '${footer}' not found

What it means

Same BEGIN/END integrity check as PEMToHex, but inside PEMToJWK.run. After matching a '-----BEGIN <label>-----' header it searches for '-----END <label>-----'; if absent it throws before attempting any jsrsasign key parsing. The footer is rebuilt from match[1], so label spacing/case must match exactly.

Source

Thrown at src/core/operations/PEMToJWK.mjs:53

    }

    /**
     * @param {string} input
     * @param {Object[]} args
     * @returns {string}
     */
    run(input, args) {
        let output = "";
        let match;
        const regex = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g;
        while ((match = regex.exec(input)) !== null) {
            // find corresponding end tag
            const indexBase64 = match.index + match[0].length;
            const header = input.substring(match.index, indexBase64);
            const footer = `-----END ${match[1]}-----`;
            const indexFooter = input.indexOf(footer, indexBase64);
            if (indexFooter === -1) {
                throw new OperationError(`PEM footer '${footer}' not found`);
            }

            const pem = input.substring(match.index, indexFooter + footer.length);
            if (match[1].indexOf("KEY") !== -1) {
                if (header === "-----BEGIN RSA PUBLIC KEY-----") {
                    throw new OperationError("Unsupported RSA public key format. Only PKCS#8 is supported.");
                }

                const key = r.KEYUTIL.getKey(pem);
                if (key.type === "DSA") {
                    throw new OperationError("DSA keys are not supported for JWK");
                }
                const jwk = r.KEYUTIL.getJWKFromKey(key);
                if (output.length > 0) {
                    output += "\n";
                }
                output += JSON.stringify(jwk);
            } else if (match[1] === "CERTIFICATE") {

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Verify each BEGIN block has a matching END block with the identical label.
  2. Paste the complete PEM including the footer line.
  3. Avoid editing PEM whitespace or label text.

Example fix

// before: header without footer
-----BEGIN PUBLIC KEY-----
MIIBIjAN...
// after: complete block
-----BEGIN PUBLIC KEY-----
MIIBIjAN...
-----END PUBLIC KEY-----
Defensive patterns

Strategy: validation

Validate before calling

function hasMatchingPemFooter(pem) {
    const re = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g;
    let m;
    while ((m = re.exec(pem)) !== null) {
        const footer = `-----END ${m[1]}-----`;
        if (pem.indexOf(footer, m.index + m[0].length) === -1) {
            return { ok: false, missing: footer };
        }
    }
    return { ok: true };
}

Try / catch

try {
    jwk = chef.PEMToJWK(input);
} catch (e) {
    if (e instanceof OperationError && /PEM footer .* not found/.test(e.message)) {
        // supply the missing END block
    } else throw e;
}

Prevention

When it happens

Trigger: A matched BEGIN header has no corresponding END footer; footer truncated; footer label mismatched in case/spacing relative to the captured header label.

Common situations: Partial copy-paste of a key/certificate PEM; truncated input; hand-edited PEM where the END label was altered.

Related errors


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