{"record":{"id":"3da76510e4443389","repo":"gchq/CyberChef","slug":"could-not-import-public-key-err","errorCode":null,"errorMessage":"Could not import public key: ${err}","messagePattern":"Could not import public key: (.+?)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/PGP.mjs","lineNumber":116,"sourceCode":"}\n\n/**\n * Import public key\n *\n * @param {string} publicKey\n * @returns {Object}\n */\nexport async function importPublicKey (publicKey) {\n    try {\n        const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({\n            armored: publicKey,\n            opts: {\n                \"no_check_keys\": true\n            }\n        });\n        return key;\n    } catch (err) {\n        throw new OperationError(`Could not import public key: ${err}`);\n    }\n}\n","sourceCodeStart":98,"sourceCodeEnd":119,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/PGP.mjs#L98-L119","documentation":"importPublicKey wraps kbpgp.KeyManager.import_from_armored_pgp in try/catch and rethrows any failure as `Could not import public key: ${err}`. Public keys have no passphrase step, so this fires purely on parse/format errors from kbpgp.","triggerScenarios":"Calling importPublicKey with a malformed armored public key, a private key block, an SSH/SSL public key, or armor that has been mangled (line wrapping stripped, header corrupted).","commonSituations":"Pasting a private key block where a public key was expected; armor copied from email client that re-wrapped long lines; missing or wrong armor headers (BEGIN PGP PUBLIC KEY BLOCK); key generated by a non-RFC 4880 compliant tool; trailing whitespace.","solutions":["Confirm the block begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.","Re-export the public key from a trusted keyring (gpg --armor --export).","Strip and re-flow the armor to RFC 4880 line lengths (max 76 chars per base64 line).","Trim trailing whitespace and newlines from the armored text before importing.","Inspect the wrapped `err` for kbpgp's specific parse failure reason."],"exampleFix":"// before\nconst pub = await PGP.importPublicKey(maybePrivateKeyOrMangled);\n\n// after\nconst cleaned = armored.trim();\nif (!cleaned.includes('BEGIN PGP PUBLIC KEY BLOCK'))\n  throw new Error('Not an OpenPGP public key block');\nconst pub = await PGP.importPublicKey(cleaned);","handlingStrategy":"try-catch","validationCode":"function looksLikeArmoredPublicKey(s) {\n  return /-----BEGIN PGP PUBLIC KEY BLOCK-----/.test(s) &&\n         /-----END PGP PUBLIC KEY BLOCK-----/.test(s);\n}\n\nif (!looksLikeArmoredPublicKey(armor.trim())) {\n  throw new Error('Input is not an OpenPGP armored public key');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await PGP.importPublicKey(armor.trim());\n} catch (e) {\n  const cause = String(e.message).replace(/^Could not import public key: /, '');\n  throw new Error('Failed to parse public key: ' + cause);\n}","preventionTips":["Confirm the armor begins with BEGIN PGP PUBLIC KEY BLOCK.","Do not paste a private key block where a public key is expected.","Re-export public keys with gpg --armor --export to ensure RFC 4880 compliance.","Re-flow base64 lines to <=76 chars and strip trailing whitespace."],"tags":["cryptography","pgp","key-management","error-wrapping"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}