-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
also an Operation for ECDSA signature conversion, as there could be multiple formats of the signature
- Loading branch information
1 parent
7a2c9dd
commit 8f182e4
Showing
6 changed files
with
727 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/** | ||
* @author cplussharp | ||
* @copyright Crown Copyright 2021 | ||
* @license Apache-2.0 | ||
*/ | ||
|
||
import Operation from "../Operation.mjs"; | ||
import OperationError from "../errors/OperationError.mjs"; | ||
import r from "jsrsasign"; | ||
|
||
/** | ||
* ECDSA Sign operation | ||
*/ | ||
class ECDSASign extends Operation { | ||
|
||
/** | ||
* ECDSASign constructor | ||
*/ | ||
constructor() { | ||
super(); | ||
|
||
this.name = "ECDSA Sign"; | ||
this.module = "Ciphers"; | ||
this.description = "Sign a plaintext message with a PEM encoded EC key."; | ||
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm"; | ||
this.inputType = "string"; | ||
this.outputType = "string"; | ||
this.args = [ | ||
{ | ||
name: "ECDSA Private Key (PEM)", | ||
type: "text", | ||
value: "-----BEGIN EC PRIVATE KEY-----" | ||
}, | ||
{ | ||
name: "Message Digest Algorithm", | ||
type: "option", | ||
value: [ | ||
"SHA-256", | ||
"SHA-384", | ||
"SHA-512", | ||
"SHA-1", | ||
"MD5" | ||
] | ||
}, | ||
{ | ||
name: "Output Format", | ||
type: "option", | ||
value: [ | ||
"ASN.1 HEX", | ||
"Concat HEX", | ||
"JSON" | ||
] | ||
} | ||
]; | ||
} | ||
|
||
/** | ||
* @param {string} input | ||
* @param {Object[]} args | ||
* @returns {string} | ||
*/ | ||
run(input, args) { | ||
const [keyPem, mdAlgo, outputFormat] = args; | ||
|
||
if (keyPem.replace("-----BEGIN EC PRIVATE KEY-----", "").length === 0) { | ||
throw new OperationError("Please enter a private key."); | ||
} | ||
|
||
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.isPrivate) { | ||
throw new OperationError("Provided key is not a private key."); | ||
} | ||
sig.init(key); | ||
const signatureASN1Hex = sig.signString(input); | ||
|
||
let result; | ||
switch (outputFormat) { | ||
case "ASN.1 HEX": | ||
result = signatureASN1Hex; | ||
break; | ||
case "Concat HEX": | ||
result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex); | ||
break; | ||
case "JSON": { | ||
const signatureRS = r.KJUR.crypto.ECDSA.parseSigHexInHexRS(signatureASN1Hex); | ||
result = JSON.stringify(signatureRS); | ||
break; | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
|
||
export default ECDSASign; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/** | ||
* @author cplussharp | ||
* @copyright Crown Copyright 2021 | ||
* @license Apache-2.0 | ||
*/ | ||
|
||
import Operation from "../Operation.mjs"; | ||
import r from "jsrsasign"; | ||
|
||
/** | ||
* ECDSA Sign operation | ||
*/ | ||
class ECDSASignatureConversion extends Operation { | ||
|
||
/** | ||
* ECDSASignatureConversion constructor | ||
*/ | ||
constructor() { | ||
super(); | ||
|
||
this.name = "ECDSA Signature Conversion"; | ||
this.module = "Ciphers"; | ||
this.description = "Convert an ECDSA signature between hex, asn1 and json."; | ||
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm"; | ||
this.inputType = "string"; | ||
this.outputType = "string"; | ||
this.args = [ | ||
{ | ||
name: "Input Format", | ||
type: "option", | ||
value: [ | ||
"Auto", | ||
"ASN.1 HEX", | ||
"Concat HEX", | ||
"JSON" | ||
] | ||
}, | ||
{ | ||
name: "Output Format", | ||
type: "option", | ||
value: [ | ||
"ASN.1 HEX", | ||
"Concat HEX", | ||
"JSON" | ||
] | ||
} | ||
]; | ||
} | ||
|
||
/** | ||
* @param {string} input | ||
* @param {Object[]} args | ||
* @returns {string} | ||
*/ | ||
run(input, args) { | ||
let inputFormat = args[0]; | ||
const outputFormat = args[1]; | ||
|
||
// detect input format | ||
if (inputFormat === "Auto") { | ||
if (input.substr(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) { | ||
inputFormat = "ASN.1 HEX"; | ||
} else if (input.indexOf("{") !== -1) { | ||
inputFormat = "JSON"; | ||
} else { | ||
inputFormat = "Concat HEX"; | ||
} | ||
} | ||
|
||
// convert input to ASN.1 hex | ||
let signatureASN1Hex; | ||
switch (inputFormat) { | ||
case "ASN.1 HEX": | ||
signatureASN1Hex = input; | ||
break; | ||
case "Concat HEX": | ||
signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input); | ||
break; | ||
case "JSON": { | ||
const inputJson = JSON.parse(input); | ||
signatureASN1Hex = r.KJUR.crypto.ECDSA.hexRSSigToASN1Sig(inputJson.r, inputJson.s); | ||
break; | ||
} | ||
} | ||
|
||
// convert ASN.1 hex to output format | ||
let result; | ||
switch (outputFormat) { | ||
case "ASN.1 HEX": | ||
result = signatureASN1Hex; | ||
break; | ||
case "Concat HEX": | ||
result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex); | ||
break; | ||
case "JSON": { | ||
const signatureRS = r.KJUR.crypto.ECDSA.parseSigHexInHexRS(signatureASN1Hex); | ||
result = JSON.stringify(signatureRS); | ||
break; | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
|
||
export default ECDSASignatureConversion; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/** | ||
* @author cplussharp | ||
* @copyright Crown Copyright 2021 | ||
* @license Apache-2.0 | ||
*/ | ||
|
||
import Operation from "../Operation.mjs"; | ||
import OperationError from "../errors/OperationError.mjs"; | ||
import r from "jsrsasign"; | ||
|
||
/** | ||
* ECDSA Verify operation | ||
*/ | ||
class ECDSAVerify extends Operation { | ||
|
||
/** | ||
* ECDSAVerify constructor | ||
*/ | ||
constructor() { | ||
super(); | ||
|
||
this.name = "ECDSA Verify"; | ||
this.module = "Ciphers"; | ||
this.description = "Verify a message against a signature and a public PEM encoded EC key."; | ||
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm"; | ||
this.inputType = "string"; | ||
this.outputType = "string"; | ||
this.args = [ | ||
{ | ||
name: "Input Format", | ||
type: "option", | ||
value: [ | ||
"Auto", | ||
"ASN.1 HEX", | ||
"Concat HEX", | ||
"JSON" | ||
] | ||
}, | ||
{ | ||
name: "Message Digest Algorithm", | ||
type: "option", | ||
value: [ | ||
"SHA-256", | ||
"SHA-384", | ||
"SHA-512", | ||
"SHA-1", | ||
"MD5" | ||
] | ||
}, | ||
{ | ||
name: "ECDSA Public Key (PEM)", | ||
type: "text", | ||
value: "-----BEGIN PUBLIC KEY-----" | ||
}, | ||
{ | ||
name: "Message", | ||
type: "text", | ||
value: "" | ||
} | ||
]; | ||
} | ||
|
||
/** | ||
* @param {string} input | ||
* @param {Object[]} args | ||
* @returns {string} | ||
*/ | ||
run(input, args) { | ||
let inputFormat = args[0]; | ||
const [, mdAlgo, keyPem, msg] = args; | ||
|
||
if (keyPem.replace("-----BEGIN PUBLIC KEY-----", "").length === 0) { | ||
throw new OperationError("Please enter a public key."); | ||
} | ||
|
||
// detect input format | ||
if (inputFormat === "Auto") { | ||
if (input.substr(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) { | ||
inputFormat = "ASN.1 HEX"; | ||
} else if (input.indexOf("{") !== -1) { | ||
inputFormat = "JSON"; | ||
} else { | ||
inputFormat = "Concat HEX"; | ||
} | ||
} | ||
|
||
// convert to ASN.1 signature | ||
let signatureASN1Hex; | ||
switch (inputFormat) { | ||
case "ASN.1 HEX": | ||
signatureASN1Hex = input; | ||
break; | ||
case "Concat HEX": | ||
signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input); | ||
break; | ||
case "JSON": { | ||
const inputJson = JSON.parse(input); | ||
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); | ||
sig.updateString(msg); | ||
const result = sig.verify(signatureASN1Hex); | ||
return result ? "Verified OK" : "Verification Failure"; | ||
} | ||
} | ||
|
||
export default ECDSAVerify; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.