{"record":{"id":"f419d80407dc66be","repo":"gchq/CyberChef","slug":"please-enter-a-private-key","errorCode":null,"errorMessage":"Please enter a private key.","messagePattern":"Please enter a private key\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/ECDSASign.mjs","lineNumber":69,"sourceCode":"                    \"ASN.1 HEX\",\n                    \"P1363 HEX\",\n                    \"JSON Web Signature\",\n                    \"Raw JSON\"\n                ]\n            }\n        ];\n    }\n\n    /**\n     * @param {string} input\n     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        const [keyPem, mdAlgo, outputFormat] = args;\n\n        if (keyPem.replace(\"-----BEGIN EC PRIVATE KEY-----\", \"\").length === 0) {\n            throw new OperationError(\"Please enter a private key.\");\n        }\n\n        const internalAlgorithmName = mdAlgo.replace(\"-\", \"\") + \"withECDSA\";\n        const sig = new r.KJUR.crypto.Signature({ alg: internalAlgorithmName });\n        const key = r.KEYUTIL.getKey(keyPem);\n        if (key.type !== \"EC\") {\n            throw new OperationError(\"Provided key is not an EC key.\");\n        }\n        if (!key.isPrivate) {\n            throw new OperationError(\"Provided key is not a private key.\");\n        }\n        sig.init(key);\n        const signatureASN1Hex = sig.signString(input);\n\n        let result;\n        switch (outputFormat) {\n            case \"ASN.1 HEX\":\n                result = signatureASN1Hex;","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/ECDSASign.mjs#L51-L87","documentation":"Thrown in ECDSASign.run when keyPem.replace('-----BEGIN EC PRIVATE KEY-----', '').length === 0. The operation's default key arg is literally '-----BEGIN EC PRIVATE KEY-----', so this check exists almost entirely to detect that the user has not replaced the placeholder header with a real key. It fires when, after removing the header line, nothing remains.","triggerScenarios":"The 'ECDSA Private Key (PEM)' field still holds the placeholder header with no base64 body, or the user pasted only the header line.","commonSituations":"First-time use where the placeholder was never overwritten; pasting a key missing the base64 block and END line; a recipe saved before the key was entered.","solutions":["Paste a complete EC private key PEM: BEGIN line, base64 body, END line.","If loading from a recipe, ensure the full PEM text was saved, not just the header.","Generate an EC key (P-256/P-384/P-521) with openssl ecparam -genkey if you do not have one."],"exampleFix":"// before (placeholder, triggers the error)\nconst key = '-----BEGIN EC PRIVATE KEY-----';\n// after (full PEM)\nconst key = '-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEE...full base64...\\n-----END EC PRIVATE KEY-----';","handlingStrategy":"validation","validationCode":"function hasPemBody(pem, header) {\n  const after = pem.replace(header, \"\");\n  return after.trim().length > 0 && pem.includes(header.replace(\"BEGIN\", \"END\"));\n}\nif (!hasPemBody(keyPem, \"-----BEGIN EC PRIVATE KEY-----\")) throw new Error(\"paste a full EC private key\");","typeGuard":"const looksLikeEcPrivateKey = (p) => /-----BEGIN EC PRIVATE KEY-----[\\s\\S]+-----END EC PRIVATE KEY-----/.test(p);","tryCatchPattern":null,"preventionTips":["Never leave the placeholder header as the key value; replace it with a full PEM.","Validate that a PEM has header, body, and footer before building the recipe.","Generate a real EC key if you do not have one."],"tags":["crypto","ecdsa","key-validation","operation-error"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}