{"record":{"id":"aa481175345373bb","repo":"gchq/CyberChef","slug":"no-s-value-in-the-signature-json-aa4811","errorCode":null,"errorMessage":"No \"s\" value in the signature JSON","messagePattern":"No \"s\" value in the signature JSON","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/ECDSAVerify.mjs","lineNumber":136,"sourceCode":"            case \"Auto\":\n                throw new OperationError(\"Signature format could not be detected\");\n            case \"ASN.1 HEX\":\n                signatureASN1Hex = input;\n                break;\n            case \"P1363 HEX\":\n                signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input);\n                break;\n            case \"JSON Web Signature\":\n                if (!inputBase64) inputBase64 = fromBase64(input, \"A-Za-z0-9-_\");\n                signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(toHexFast(inputBase64));\n                break;\n            case \"Raw JSON\": {\n                if (!inputJson) inputJson = JSON.parse(input);\n                if (!inputJson.r) {\n                    throw new OperationError('No \"r\" value in the signature JSON');\n                }\n                if (!inputJson.s) {\n                    throw new OperationError('No \"s\" value in the signature JSON');\n                }\n                signatureASN1Hex = r.KJUR.crypto.ECDSA.hexRSSigToASN1Sig(inputJson.r, inputJson.s);\n                break;\n            }\n        }\n\n        // verify signature\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.isPublic) {\n            throw new OperationError(\"Provided key is not a public key.\");\n        }\n        sig.init(key);\n        const messageStr = Utils.convertToByteString(msg, msgFormat);","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/ECDSAVerify.mjs#L118-L154","documentation":"Thrown in ECDSAVerify.run, Raw JSON branch, when r is present but s is falsy. Companion to the r guard: a raw-JSON ECDSA signature needs both scalars, and a missing s is rejected here.","triggerScenarios":"Input Format resolved to Raw JSON and the JSON has a valid r but no s - e.g. {\"r\":\"...\"} or a second field under a different name.","commonSituations":"Truncated JSON missing s; a field named differently ('S'); only r half captured.","solutions":["Ensure JSON has lowercase 's' alongside 'r'.","Rename mismatched fields from the source.","Re-extract both scalars from the original signature."],"exampleFix":"// before\nverifyRun('{\"r\":\"bb...\"}', ['Raw JSON', ...]);  // missing s\n// after\nverifyRun('{\"r\":\"bb...\",\"s\":\"a3...\"}', ['Raw JSON', ...]);","handlingStrategy":"validation","validationCode":"const o = JSON.parse(sig);\nif (!o || typeof o !== \"object\" || !o.s) throw new Error(\"signature JSON needs an 's' field\");","typeGuard":"const hasS = (o) => o != null && typeof o === \"object\" && Object.prototype.hasOwnProperty.call(o, \"s\");","tryCatchPattern":null,"preventionTips":["Capture both scalars when serialising a raw-JSON signature.","Validate both r and s exist before building the recipe."],"tags":["crypto","ecdsa","signature","json","operation-error"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}