{"record":{"id":"b376e85681430d55","repo":"gchq/CyberChef","slug":"could-not-import-private-key-err","errorCode":null,"errorMessage":"Could not import private key: ${err}","messagePattern":"Could not import private key: (.+?)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/PGP.mjs","lineNumber":96,"sourceCode":"    try {\n        const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({\n            armored: privateKey,\n            opts: {\n                \"no_check_keys\": true\n            }\n        });\n        if (key.is_pgp_locked()) {\n            if (passphrase) {\n                await promisify(key.unlock_pgp.bind(key))({\n                    passphrase\n                });\n            } else {\n                throw new OperationError(\"Did not provide passphrase with locked private key.\");\n            }\n        }\n        return key;\n    } catch (err) {\n        throw new OperationError(`Could not import private key: ${err}`);\n    }\n}\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;","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/PGP.mjs#L78-L114","documentation":"importPrivateKey wraps its entire body in try/catch and rethrows any failure as `Could not import private key: ${err}`. This catches: (a) kbpgp failing to parse the armored key (corrupt armor, bad base64, wrong format), (b) unlock_pgp failing because the passphrase is wrong, and (c) the inner 'Did not provide passphrase' OperationError being re-caught and rewrapped - so the no-passphrase message appears nested inside this one.","triggerScenarios":"Calling importPrivateKey with a malformed armored block; with a non-OpenPGP key (OpenSSL/SSH format); with the wrong passphrase; or omitting the passphrase on a locked key (the inner throw at line 91 is caught here).","commonSituations":"Wrong key format (PEM/OpenSSL vs OpenPGP armor); copy-paste stripped the armor headers or checksum; typo in the passphrase; key generated by a newer/older kbpgp version with incompatible packaging; trailing whitespace/newline corruption in the armored blob.","solutions":["Inspect the wrapped `err` in the caught exception - it distinguishes parse failure from wrong passphrase.","Confirm the input is a valid OpenPGP ASCII-armored private key (BEGIN PGP PRIVATE KEY BLOCK).","Verify the passphrase against the same key with gpg --list-packets or gpg --import.","Trim stray whitespace/newlines from the armored text before importing.","If using a locked key, ensure the passphrase is supplied (see error 107)."],"exampleFix":"// before\ntry {\n  const key = await PGP.importPrivateKey(maybeCorruptedArmor, pw);\n} catch (e) {\n  console.error(e.message); // opaque wrapped message\n}\n\n// after - surface the underlying cause\ntry {\n  const key = await PGP.importPrivateKey(armor.trim(), pw);\n} catch (e) {\n  const cause = e.message.replace(/^Could not import private key: /, '');\n  if (/passphrase/i.test(cause)) showUser('Wrong passphrase');\n  else if (/parse|armor|base64/i.test(cause)) showUser('Key is malformed');\n}","handlingStrategy":"try-catch","validationCode":"function looksLikeArmoredPrivateKey(s) {\n  return /-----BEGIN PGP PRIVATE KEY BLOCK-----/.test(s) &&\n         /-----END PGP PRIVATE KEY BLOCK-----/.test(s);\n}\n\nif (!looksLikeArmoredPrivateKey(armor.trim())) {\n  throw new Error('Input is not an OpenPGP armored private key');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await PGP.importPrivateKey(armor.trim(), passphrase);\n} catch (e) {\n  const cause = String(e.message).replace(/^Could not import private key: /, '');\n  if (/passphrase/i.test(cause)) throw new Error('Wrong passphrase');\n  if (/parse|armor|base64|crc/i.test(cause)) throw new Error('Malformed private key armor');\n  throw new Error(cause);\n}","preventionTips":["Trim whitespace/newlines from armored key text before importing.","Inspect the wrapped cause string to differentiate parse vs passphrase errors.","Confirm the block is OpenPGP (BEGIN PGP PRIVATE KEY BLOCK), not OpenSSL/SSH.","Verify the passphrase with gpg --list-packets before importing."],"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"}