diff --git a/src/core/operations/ECDSASign.mjs b/src/core/operations/ECDSASign.mjs index 5cce8cc2..0278eeeb 100644 --- a/src/core/operations/ECDSASign.mjs +++ b/src/core/operations/ECDSASign.mjs @@ -48,7 +48,7 @@ class ECDSASign extends Operation { value: [ "ASN.1 HEX", "P1363 HEX", - "JSON" + "Raw JSON" ] } ]; @@ -86,7 +86,7 @@ class ECDSASign extends Operation { case "P1363 HEX": result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex); break; - case "JSON": { + case "Raw JSON": { const signatureRS = r.KJUR.crypto.ECDSA.parseSigHexInHexRS(signatureASN1Hex); result = JSON.stringify(signatureRS); break; diff --git a/src/core/operations/ECDSASignatureConversion.mjs b/src/core/operations/ECDSASignatureConversion.mjs index 1dfcb4d1..49c5ef53 100644 --- a/src/core/operations/ECDSASignatureConversion.mjs +++ b/src/core/operations/ECDSASignatureConversion.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; import r from "jsrsasign"; /** @@ -32,7 +33,7 @@ class ECDSASignatureConversion extends Operation { "Auto", "ASN.1 HEX", "P1363 HEX", - "JSON" + "Raw JSON" ] }, { @@ -41,7 +42,7 @@ class ECDSASignatureConversion extends Operation { value: [ "ASN.1 HEX", "P1363 HEX", - "JSON" + "Raw JSON" ] } ]; @@ -57,11 +58,19 @@ class ECDSASignatureConversion extends Operation { const outputFormat = args[1]; // detect input format + let inputJson; if (inputFormat === "Auto") { - if (input.substr(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) { + try { + inputJson = JSON.parse(input); + if (typeof(inputJson) === "object") { + inputFormat = "Raw JSON"; + } + } catch {} + } + + if (inputFormat === "Auto") { + if (input.substring(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) { inputFormat = "ASN.1 HEX"; - } else if (input.indexOf("{") !== -1) { - inputFormat = "JSON"; } else { inputFormat = "P1363 HEX"; } @@ -76,8 +85,14 @@ class ECDSASignatureConversion extends Operation { case "P1363 HEX": signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input); break; - case "JSON": { - const inputJson = JSON.parse(input); + 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; } @@ -92,7 +107,7 @@ class ECDSASignatureConversion extends Operation { case "P1363 HEX": result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex); break; - case "JSON": { + case "Raw JSON": { const signatureRS = r.KJUR.crypto.ECDSA.parseSigHexInHexRS(signatureASN1Hex); result = JSON.stringify(signatureRS); break; diff --git a/src/core/operations/ECDSAVerify.mjs b/src/core/operations/ECDSAVerify.mjs index 8f3174a2..2cd38398 100644 --- a/src/core/operations/ECDSAVerify.mjs +++ b/src/core/operations/ECDSAVerify.mjs @@ -33,7 +33,7 @@ class ECDSAVerify extends Operation { "Auto", "ASN.1 HEX", "P1363 HEX", - "JSON" + "Raw JSON" ] }, { @@ -74,11 +74,19 @@ class ECDSAVerify extends Operation { } // detect input format + let inputJson; if (inputFormat === "Auto") { - if (input.substr(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) { + try { + inputJson = JSON.parse(input); + if (typeof(inputJson) === "object") { + inputFormat = "Raw JSON"; + } + } catch {} + } + + if (inputFormat === "Auto") { + if (input.substring(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) { inputFormat = "ASN.1 HEX"; - } else if (input.indexOf("{") !== -1) { - inputFormat = "JSON"; } else { inputFormat = "P1363 HEX"; } @@ -93,8 +101,14 @@ class ECDSAVerify extends Operation { case "P1363 HEX": signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input); break; - case "JSON": { - const inputJson = JSON.parse(input); + 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; } diff --git a/tests/operations/tests/ECDSA.mjs b/tests/operations/tests/ECDSA.mjs index 8fe93ef3..f0d4305a 100644 --- a/tests/operations/tests/ECDSA.mjs +++ b/tests/operations/tests/ECDSA.mjs @@ -271,6 +271,28 @@ TestRegister.addTests([ } ] }, + { + name: "ECDSA Verify: JSON signature missing r", + input: JSON.stringify({s: JSON.parse(P256.signature.sha256.json).s}), + expectedOutput: 'No "r" value in the signature JSON', + recipeConfig: [ + { + "op": "ECDSA Verify", + "args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT] + } + ] + }, + { + name: "ECDSA Verify: JSON signature missing s", + input: JSON.stringify({r: JSON.parse(P256.signature.sha256.json).r}), + expectedOutput: 'No "s" value in the signature JSON', + recipeConfig: [ + { + "op": "ECDSA Verify", + "args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT] + } + ] + }, { name: "ECDSA Verify: Using private key fails", input: P256.signature.sha256.asn1, @@ -324,7 +346,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "ECDSA Signature Conversion", - "args": ["Auto", "JSON"] + "args": ["Auto", "Raw JSON"] } ] }, @@ -357,7 +379,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "ECDSA Signature Conversion", - "args": ["Auto", "JSON"] + "args": ["Auto", "Raw JSON"] } ] }, @@ -390,7 +412,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "ECDSA Signature Conversion", - "args": ["Auto", "JSON"] + "args": ["Auto", "Raw JSON"] } ] }