UNPKG

cranker-router

Version:
140 lines (123 loc) 4.83 kB
const pki = require("node-forge").pki; const makeCa = function () { const serialNumber = (function () { let serial = 1; return function() { serial = serial + 1; const serialString = "" + serial; return serialString.padStart(5, ""); // Not fantastic but enough for in memory ca } })(); const caKeyPair = pki.rsa.generateKeyPair(2048); const caCert = pki.createCertificate(); caCert.publicKey = caKeyPair.publicKey; caCert.serialNumber = serialNumber(); caCert.validity.notBefore = new Date(); caCert.validity.notAfter = new Date(); caCert.validity.notAfter.setFullYear( caCert.validity.notBefore.getFullYear() + 1 ); const caAttrs = [ {name: "commonName", value: "example-ca.org"}, {name: "countryName", value: "GB"}, {name: "localityName", value: "GB"}, {name: "organizationName", value: "Example CA"}, {shortName: "OU", value: "test"} ]; caCert.setSubject(caAttrs); caCert.setIssuer(caAttrs); caCert.setExtensions([ { name: "basicConstraints", cA: true }, { name: "keyUsage", keyCertSign: true, digitalSignature: true, keyEncipherment: true, dataEncipherment: true }, { name: "extKeyUsage", serverAuth: true, clientAuth: true, codeSigning: true, emailProtection: true, timeStamping: true }, { name: "nsCertType", client: true, server: true, email: true, objsign: true, sslCA: true, emailCA: true, objCA: true }, { name: "subjectAltName", altNames: [ { type: 6, value: "http://www.example-ca.org" }, { type: 7, ip: "127.0.0.1" } ]}, { name: "subjectKeyIdentifier" } ]); caCert.sign(caKeyPair.privateKey); const caStore = pki.createCaStore([pki.certificateToPem(caCert)]); return { issue: function (publicKeyInPem, csrInPem) { const publicKey = pki.publicKeyFromPem(publicKeyInPem); const csrToSign = pki.certificationRequestFromPem(csrInPem); const cert = pki.createCertificate(); cert.publicKey = publicKey; cert.serialNumber = serialNumber(); console.log("fake ca issuing serial number", cert.serialNumber); cert.validity.notBefore = new Date(); cert.validity.notAfter = new Date(); cert.validity.notAfter.setFullYear( cert.validity.notBefore.getFullYear() + 1 ); cert.setSubject(csrToSign.subject.attributes); // To CA sign the cert the CA simply does this: cert.setIssuer(caAttrs); const extensions = csrToSign.getAttribute({name: "extensionRequest"}).extensions; extensions.push.apply(extensions, [ { name: "basicConstraints", cA: true }, { name: "keyUsage", keyCertSign: true, digitalSignature: true, nonRepudiation: true, keyEncipherment: true, dataEncipherment: true } ]); cert.setExtensions(extensions); cert.sign(caKeyPair.privateKey); return { cert: pki.certificateToPem(cert), ca: pki.certificateToPem(caCert) }; } }; }; const makeCsr = function () { const keys = pki.rsa.generateKeyPair(2048); const csr = pki.createCertificationRequest(); csr.publicKey = keys.publicKey; csr.setSubject([ {name: "commonName", value: "localhost"}, {name: "countryName", value: "GB"}, {name: "localityName", value: "GB"}, {name: "organizationName", value: "Example"}, {shortName: "OU", value: "Example" }, ]); csr.setAttributes([ { name: "unstructuredName", value: "My Example Cert" }, { name: "extensionRequest", extensions: [{ name: "subjectAltName", altNames: [ { type: 2, value: "localhost" }, { type: 2, value: "other.domain.com" }, { type: 2, value: "www.example.org" } ] }] } ]); // We sign the certification request csr.sign(keys.privateKey); // We should verify it before sending const verifiedCSR = csr.verify(); // Convert it to PEM to send to the CA const csrInPem = pki.certificationRequestToPem(csr); const pemPrivate = pki.privateKeyToPem(keys.privateKey); const pemPublic = pki.publicKeyToPem(keys.publicKey); return [pemPrivate, pemPublic, csrInPem]; }; exports.makeCa = makeCa; exports.makeCsr = makeCsr; // End