118 lines
3.0 KiB
JavaScript
118 lines
3.0 KiB
JavaScript
/**
|
|
* @author cplussharp
|
|
* @copyright Crown Copyright 2021
|
|
* @license Apache-2.0
|
|
*/
|
|
|
|
import Operation from "../Operation.mjs";
|
|
import { cryptNotice } from "../lib/Crypt.mjs";
|
|
import { toBase64 } from "../lib/Base64.mjs";
|
|
import {
|
|
generateEcKeyPair,
|
|
publicKeyToSpkiPem,
|
|
privateKeyToPkcs8Pem,
|
|
} from "../lib/Ecdsa.mjs";
|
|
|
|
/**
|
|
* Generate ECDSA Key Pair operation
|
|
*/
|
|
class GenerateECDSAKeyPair extends Operation {
|
|
|
|
/**
|
|
* GenerateECDSAKeyPair constructor
|
|
*/
|
|
constructor() {
|
|
super();
|
|
|
|
this.name = "Generate ECDSA Key Pair";
|
|
this.module = "Ciphers";
|
|
this.description = `Generate an ECDSA key pair with a given Curve.<br><br>${cryptNotice}`;
|
|
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm";
|
|
this.inputType = "string";
|
|
this.outputType = "string";
|
|
this.args = [
|
|
{
|
|
name: "Elliptic Curve",
|
|
type: "option",
|
|
value: [
|
|
"P-256",
|
|
"P-384",
|
|
"P-521"
|
|
]
|
|
},
|
|
{
|
|
name: "Output Format",
|
|
type: "option",
|
|
value: [
|
|
"PEM",
|
|
"DER",
|
|
"JWK"
|
|
]
|
|
}
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param {string} input
|
|
* @param {Object[]} args
|
|
* @returns {string}
|
|
*/
|
|
async run(input, args) {
|
|
const [curveName, outputFormat] = args;
|
|
const pair = generateEcKeyPair(curveName);
|
|
|
|
switch (outputFormat) {
|
|
case "PEM":
|
|
return publicKeyToSpkiPem(pair) + privateKeyToPkcs8Pem(pair);
|
|
case "DER":
|
|
return bytesToHex(pair.d);
|
|
case "JWK": {
|
|
const pubJwk = {
|
|
kty: "EC",
|
|
crv: curveName,
|
|
x: b64url(pair.x),
|
|
y: b64url(pair.y),
|
|
"key_ops": ["verify"],
|
|
kid: "PublicKey",
|
|
};
|
|
const privJwk = {
|
|
kty: "EC",
|
|
crv: curveName,
|
|
x: b64url(pair.x),
|
|
y: b64url(pair.y),
|
|
d: b64url(pair.d),
|
|
"key_ops": ["sign"],
|
|
kid: "PrivateKey",
|
|
};
|
|
return JSON.stringify({ keys: [privJwk, pubJwk] }, null, 4);
|
|
}
|
|
default:
|
|
throw new Error(`Unsupported output format: ${outputFormat}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base64url-encode a byte array (no padding, URL-safe alphabet).
|
|
*
|
|
* @param {Uint8Array} bytes
|
|
* @returns {string}
|
|
*/
|
|
function b64url(bytes) {
|
|
return toBase64(bytes, "A-Za-z0-9-_");
|
|
}
|
|
|
|
/**
|
|
* Convert a byte array to a lowercase hex string.
|
|
*
|
|
* @param {Uint8Array} bytes
|
|
* @returns {string}
|
|
*/
|
|
function bytesToHex(bytes) {
|
|
let out = "";
|
|
for (const b of bytes) out += b.toString(16).padStart(2, "0");
|
|
return out;
|
|
}
|
|
|
|
export default GenerateECDSAKeyPair;
|