I create a CA certificate by this code:
// Create a new certificate authority (CA) key pair
const caKeys = forge.pki.rsa.generateKeyPair(4096);
// Create a new certificate authority (CA) certificate
const cert = forge.pki.createCertificate();
cert.publicKey = caKeys.publicKey;
cert.signatureAlgorithm = forge.pki.oids.sha256WithRSAEncryption;
cert.serialNumber = "01";
// Set the subject of the CA certificate
cert.setSubject([
{ name: "countryName", value: "SK" },
{ name: "commonName", value: "Primantro-Canny-Root-CA" },
]);
// Set validity period of the CA certificate
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); // 1 year validity
var attrs = [
{ name: "commonName", value: "name" },
{ name: "countryName", value: "AT" },
{ name: "organizationName", value: "Org"},
{ shortName: "OU", value: "OU" },
];
cert.setSubject(attrs);
// alternatively set subject from a csr
//cert.setSubject(csr.subject.attributes);
cert.setIssuer(attrs);
cert.setExtensions([
{ name: "basicConstraints", cA: true },
{
name: "keyUsage",
keyCertSign: true,
digitalSignature: true,
nonRepudiation: 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: "subjectKeyIdentifier",
},
]);
// Sign the CA certificate with its own private key
cert.sign(caKeys.privateKey, forge.md.sha256.create());
// Save the CA private key to a file
const caPrivateKeyPem = forge.pki.privateKeyToPem(caKeys.privateKey);
fs.writeFileSync(keyPath, caPrivateKeyPem);
// Save the CA certificate to a file
const caPublicPem = forge.pki.publicKeyToPem(cert.publicKey);
fs.writeFileSync(pemPath, caPublicPem);
// Convert the certificate to CRT format
const crtCert = forge.pki.certificateToPem(cert);
fs.writeFileSync(crtPath, crtCert);
return { crt: crtCert, pem: caPublicPem, key: caPrivateKeyPem };
then I use the returned value to create a ssl certificate for localhost by this code:
const ca = await localhostCA();
const caPrivateKeyPem = ca.key;
const caCertPem = ca.crt;
const caPrivateKey = forge.pki.privateKeyFromPem(caPrivateKeyPem);
const caCert = forge.pki.certificateFromPem(caCertPem);
// Create a new key pair for the server
const serverKeys = forge.pki.rsa.generateKeyPair(2048);
const serverCert = forge.pki.createCertificate();
serverCert.signatureAlgorithm = forge.pki.oids.sha256WithRSAEncryption;
// Set the subject of the server certificate
serverCert.publicKey = serverKeys.publicKey;
serverCert.setSubject([
{ name: "countryName", value: "SK" },
{ name: "stateOrProvinceName", value: "YourState" },
{ name: "localityName", value: "YourCity" },
{ name: "organizationName", value: "Example-Certificates" },
{ name: "commonName", value: "localhost.local" },
]);
// Set the issuer to the Root CA
serverCert.setIssuer(caCert.subject.attributes);
// Set the validity period of the server certificate
serverCert.validity.notBefore = new Date();
serverCert.validity.notAfter = new Date();
serverCert.validity.notAfter.setFullYear(serverCert.validity.notBefore.getFullYear() + 1); // 1 year validity
// Set the extensions for the server certificate
serverCert.setExtensions([
{
name: "subjectAltName",
altNames: [
{ type: 2, value: "localhost" },
{ type: 2, value: "fake1.local" },
{ type: 2, value: "fake2.local" },
],
},
{
name: "keyUsage",
keyEncipherment: true,
digitalSignature: true,
nonRepudiation: true,
keyAgreement: true,
},
]);
// Sign the server certificate with the Root CA private key
serverCert.sign(caPrivateKey, forge.md.sha256.create());
// Save the server private key to a file
const serverPrivateKeyPem = forge.pki.privateKeyToPem(serverKeys.privateKey);
// fs.writeFileSync("localhost.key", serverPrivateKeyPem);
// Save the server certificate request to a file (optional)
// const serverCertReqPem = forge.pki.certificationRequestToPem(
// forge.pki.createCertificationRequest({ publicKey: serverKeys.publicKey })
// );
// fs.writeFileSync("localhost.csr", serverCertReqPem);
// Save the server certificate to a file
const serverCertPem = forge.pki.certificateToPem(serverCert);
// fs.writeFileSync("localhost.crt", serverCertPem);
return {
cert: serverCertPem,
key: serverPrivateKeyPem,
ca: ca.crt,
};
Then I set the ssl certificate for node's https server and import the CA certificate in Firefox's certificate manager under Authorities tab. But Firefox is still giving me error
SEC_ERROR_UNKNOWN_ISSUER
I tried to recreate this tutorial with node-forge, but apparently, I was unsuccessfull.
When I import the CA certificate into windows storage, the chrome works correctly and accepts the CA and SSL certificates. But firefox does not. So how can I make Firefox accept my self-made certificate?
Turns out, the certs were so bad, they basically didn't work anywhere. But I fixed it, here's the code:
It's a bit not clean, so tidy it up to your preferences.