diff --git a/src/core/operations/PubKeyFromCSR.mjs b/src/core/operations/PubKeyFromCSR.mjs index 46586891..af7615a2 100644 --- a/src/core/operations/PubKeyFromCSR.mjs +++ b/src/core/operations/PubKeyFromCSR.mjs @@ -2,6 +2,8 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import forge from "node-forge"; +const { asn1, pki, util } = forge; + /** * Public Key from CSR operation */ @@ -12,7 +14,6 @@ class PubKeyFromCSR extends Operation { */ constructor() { super(); - this.name = "Public Key from CSR"; this.module = "PublicKey"; this.description = "Extracts the Public Key from a Certificate Signing Request."; @@ -33,7 +34,6 @@ class PubKeyFromCSR extends Operation { let match; const regex = /-----BEGIN (CERTIFICATE REQUEST)-----/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); @@ -41,16 +41,35 @@ class PubKeyFromCSR extends Operation { throw new OperationError(`CSR footer '${footer}' not found`); } const csrString = input.substring(match.index, indexFooter + footer.length); - let pubKey; + + let pubKeyPem; try { - // Parse the CSR and extract the public key. - pubKey = forge.pki.certificationRequestFromPem(csrString).publicKey; - } catch (err) { - throw new OperationError(`Failed to parse CSR or extract public key: ${err}`); + // RSA + const csr = pki.certificationRequestFromPem(csrString); + pubKeyPem = pki.publicKeyToPem(csr.publicKey); + } catch (e) { + if (!e.message.includes("OID is not RSA")) { + throw new OperationError(`Failed to parse CSR or extract public key: ${e}`); + } + // EC + try { + const csrDer = util.decode64( + csrString + .replace("-----BEGIN CERTIFICATE REQUEST-----", "") + .replace("-----END CERTIFICATE REQUEST-----", "") + .replace(/\s+/g, "") + ); + const csrAsn1 = asn1.fromDer(csrDer); + const certReqInfo = csrAsn1.value[0]; + const spki = certReqInfo.value[2]; + const spkiDer = asn1.toDer(spki).getBytes(); + const spkiB64 = util.encode64(spkiDer); + pubKeyPem = `-----BEGIN PUBLIC KEY-----\n${spkiB64.match(/.{1,64}/g).join("\n")}\n-----END PUBLIC KEY-----\n`; + } catch (err) { + throw new OperationError(`Failed to parse CSR or extract public key: ${err}`); + } } - // Convert the extracted public key object to PEM format. - const pubKeyPem = forge.pki.publicKeyToPem(pubKey); output += pubKeyPem; } return output;