gchq/CyberChef · error · OperationError

Unsupported RSA public key format. Only PKCS#8 is supported.

Error message

Unsupported RSA public key format. Only PKCS#8 is supported.

What it means

PEMToJWK deliberately rejects PKCS#1 RSA public keys. The header string is compared to the literal '-----BEGIN RSA PUBLIC KEY-----' (the PKCS#1 marker); only PKCS#8 SubjectPublicKeyInfo ('-----BEGIN PUBLIC KEY-----') is accepted because jsrsasign's KEYUTIL.getJWKFromKey expects PKCS#8. A PKCS#1 header short-circuits before any parsing.

Source

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

     */
    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") {
                const cert = new r.X509();
                cert.readCertPEM(pem);
                const key = cert.getPublicKey();
                const jwk = r.KEYUTIL.getJWKFromKey(key);
                if (output.length > 0) {
                    output += "\n";

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Convert the key to PKCS#8: openssl rsa -RSAPublicKey_in -in pub.pem -pubout -out pub_pkcs8.pem (the -pubout default writes PKCS#8 'PUBLIC KEY').
  2. Re-export the public key from its source as SubjectPublicKeyInfo / PKCS#8.
  3. Confirm the resulting header reads '-----BEGIN PUBLIC KEY-----' with no 'RSA' prefix.

Example fix

// before (PKCS#1, rejected)
-----BEGIN RSA PUBLIC KEY-----
...
// after (PKCS#8, accepted)
-----BEGIN PUBLIC KEY-----
...
Defensive patterns

Strategy: validation

Validate before calling

function isPkcs8PublicKey(pem) {
    return /-----BEGIN PUBLIC KEY-----/.test(pem)
        && !/-----BEGIN RSA PUBLIC KEY-----/.test(pem);
}

Type guard

const isPkcs8RsaPublicKey = (pem) =>
    typeof pem === 'string' &&
    pem.includes('-----BEGIN PUBLIC KEY-----') &&
    !pem.includes('-----BEGIN RSA PUBLIC KEY-----');

Prevention

When it happens

Trigger: User feeds a PKCS#1 RSA public key whose header is '-----BEGIN RSA PUBLIC KEY-----'. Common source: OpenSSL legacy 'openssl rsa -RSAPublicKey_out' which emits PKCS#1, or Java RSA exports.

Common situations: Keys exported with older OpenSSL defaults that produce PKCS#1; interop with systems emitting 'RSA PUBLIC KEY'; copy-paste from a tool that wraps RSA public keys in PKCS#1.

Related errors


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