Merge pull request #1642 from cplussharp/pubkey-from-cert

This commit is contained in:
a3957273 2024-04-13 21:24:27 +01:00 committed by GitHub
commit edc23a860d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 624 additions and 1 deletions

View file

@ -182,7 +182,9 @@
"RSA Encrypt",
"RSA Decrypt",
"Parse SSH Host Key",
"Parse CSR"
"Parse CSR",
"Public Key from Certificate",
"Public Key from Private Key"
]
},
{

View file

@ -0,0 +1,68 @@
/**
* @author cplussharp
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import r from "jsrsasign";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Public Key from Certificate operation
*/
class PubKeyFromCert extends Operation {
/**
* PubKeyFromCert constructor
*/
constructor() {
super();
this.name = "Public Key from Certificate";
this.module = "PublicKey";
this.description = "Extracts the Public Key from a Certificate.";
this.infoURL = "https://en.wikipedia.org/wiki/X.509";
this.inputType = "string";
this.outputType = "string";
this.args = [];
this.checks = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let output = "";
let match;
const regex = /-----BEGIN CERTIFICATE-----/g;
while ((match = regex.exec(input)) !== null) {
// find corresponding end tag
const indexBase64 = match.index + match[0].length;
const footer = "-----END CERTIFICATE-----";
const indexFooter = input.indexOf(footer, indexBase64);
if (indexFooter === -1) {
throw new OperationError(`PEM footer '${footer}' not found`);
}
const certPem = input.substring(match.index, indexFooter + footer.length);
const cert = new r.X509();
cert.readCertPEM(certPem);
let pubKey;
try {
pubKey = cert.getPublicKey();
} catch {
throw new OperationError("Unsupported public key type");
}
const pubKeyPem = r.KEYUTIL.getPEM(pubKey);
// PEM ends with '\n', so a new key always starts on a new line
output += pubKeyPem;
}
return output;
}
}
export default PubKeyFromCert;

View file

@ -0,0 +1,82 @@
/**
* @author cplussharp
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import r from "jsrsasign";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Public Key from Private Key operation
*/
class PubKeyFromPrivKey extends Operation {
/**
* PubKeyFromPrivKey constructor
*/
constructor() {
super();
this.name = "Public Key from Private Key";
this.module = "PublicKey";
this.description = "Extracts the Public Key from a Private Key.";
this.infoURL = "https://en.wikipedia.org/wiki/PKCS_8";
this.inputType = "string";
this.outputType = "string";
this.args = [];
this.checks = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let output = "";
let match;
const regex = /-----BEGIN ((RSA |EC |DSA )?PRIVATE KEY)-----/g;
while ((match = regex.exec(input)) !== null) {
// find corresponding end tag
const indexBase64 = match.index + match[0].length;
const footer = `-----END ${match[1]}-----`;
const indexFooter = input.indexOf(footer, indexBase64);
if (indexFooter === -1) {
throw new OperationError(`PEM footer '${footer}' not found`);
}
const privKeyPem = input.substring(match.index, indexFooter + footer.length);
let privKey;
try {
privKey = r.KEYUTIL.getKey(privKeyPem);
} catch (err) {
throw new OperationError(`Unsupported key type: ${err}`);
}
let pubKey;
if (privKey.type && privKey.type === "EC") {
pubKey = new r.KJUR.crypto.ECDSA({ curve: privKey.curve });
pubKey.setPublicKeyHex(privKey.generatePublicKeyHex());
} else if (privKey.type && privKey.type === "DSA") {
if (!privKey.y) {
throw new OperationError(`DSA Private Key in PKCS#8 is not supported`);
}
pubKey = new r.KJUR.crypto.DSA();
pubKey.setPublic(privKey.p, privKey.q, privKey.g, privKey.y);
} else if (privKey.n && privKey.e) {
pubKey = new r.RSAKey();
pubKey.setPublic(privKey.n, privKey.e);
} else {
throw new OperationError(`Unsupported key type`);
}
const pubKeyPem = r.KEYUTIL.getPEM(pubKey);
// PEM ends with '\n', so a new key always starts on a new line
output += pubKeyPem;
}
return output;
}
}
export default PubKeyFromPrivKey;