gchq/CyberChef · error · OperationError

No "s" value in the signature JSON

Error message

No "s" value in the signature JSON

What it means

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.

Source

Thrown at src/core/operations/ECDSAVerify.mjs:136

            case "Auto":
                throw new OperationError("Signature format could not be detected");
            case "ASN.1 HEX":
                signatureASN1Hex = input;
                break;
            case "P1363 HEX":
                signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input);
                break;
            case "JSON Web Signature":
                if (!inputBase64) inputBase64 = fromBase64(input, "A-Za-z0-9-_");
                signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(toHexFast(inputBase64));
                break;
            case "Raw JSON": {
                if (!inputJson) inputJson = JSON.parse(input);
                if (!inputJson.r) {
                    throw new OperationError('No "r" value in the signature JSON');
                }
                if (!inputJson.s) {
                    throw new OperationError('No "s" value in the signature JSON');
                }
                signatureASN1Hex = r.KJUR.crypto.ECDSA.hexRSSigToASN1Sig(inputJson.r, inputJson.s);
                break;
            }
        }

        // verify signature
        const internalAlgorithmName = mdAlgo.replace("-", "") + "withECDSA";
        const sig = new r.KJUR.crypto.Signature({ alg: internalAlgorithmName });
        const key = r.KEYUTIL.getKey(keyPem);
        if (key.type !== "EC") {
            throw new OperationError("Provided key is not an EC key.");
        }
        if (!key.isPublic) {
            throw new OperationError("Provided key is not a public key.");
        }
        sig.init(key);
        const messageStr = Utils.convertToByteString(msg, msgFormat);

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Ensure JSON has lowercase 's' alongside 'r'.
  2. Rename mismatched fields from the source.
  3. Re-extract both scalars from the original signature.

Example fix

// before
verifyRun('{"r":"bb..."}', ['Raw JSON', ...]);  // missing s
// after
verifyRun('{"r":"bb...","s":"a3..."}', ['Raw JSON', ...]);
Defensive patterns

Strategy: validation

Validate before calling

const o = JSON.parse(sig);
if (!o || typeof o !== "object" || !o.s) throw new Error("signature JSON needs an 's' field");

Type guard

const hasS = (o) => o != null && typeof o === "object" && Object.prototype.hasOwnProperty.call(o, "s");

Prevention

When it happens

Trigger: 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.

Common situations: Truncated JSON missing s; a field named differently ('S'); only r half captured.

Related errors


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