proxy/scripts/generate-ca.js
2026-06-30 23:00:35 +08:00

53 lines
2.3 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const forge = require('node-forge');
const rootDir = path.resolve(__dirname, '..');
const rawConfigText = fs.readFileSync(path.join(rootDir, 'config.json'), 'utf8');
const configText = rawConfigText.charCodeAt(0) === 0xfeff ? rawConfigText.slice(1) : rawConfigText;
const config = JSON.parse(configText);
const certDir = path.resolve(rootDir, config.certDir || 'certs');
const keyPath = path.join(certDir, 'rootCA.key.pem');
const certPath = path.join(certDir, 'rootCA.cert.pem');
const certDerPath = path.join(certDir, 'rootCA.cert.cer');
fs.mkdirSync(certDir, { recursive: true });
if (fs.existsSync(keyPath) || fs.existsSync(certPath) || fs.existsSync(certDerPath)) {
console.error('Root CA already exists. Delete certs/rootCA.* first if you intentionally want to regenerate it.');
process.exit(1);
}
console.log('Generating 2048-bit RSA root CA...');
const keys = forge.pki.rsa.generateKeyPair(2048);
const cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16)).replace(/^00/, '01');
cert.validity.notBefore = new Date(Date.now() - 60 * 1000);
cert.validity.notAfter = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000);
cert.setSubject([
{ name: 'commonName', value: 'Local Node MITM Proxy Root CA' },
{ name: 'organizationName', value: 'Local Development' },
{ shortName: 'OU', value: 'Debug Proxy' },
]);
cert.setIssuer(cert.subject.attributes);
cert.setExtensions([
{ name: 'basicConstraints', cA: true, critical: true },
{ name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },
{ name: 'subjectKeyIdentifier' },
]);
cert.sign(keys.privateKey, forge.md.sha256.create());
const keyPem = forge.pki.privateKeyToPem(keys.privateKey);
const certPem = forge.pki.certificateToPem(cert);
const certDer = Buffer.from(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes(), 'binary');
fs.writeFileSync(keyPath, keyPem, 'utf8');
fs.writeFileSync(certPath, certPem, 'utf8');
fs.writeFileSync(certDerPath, certDer);
console.log(`Created private key: ${keyPath}`);
console.log(`Created PEM cert: ${certPath}`);
console.log(`Created DER cert: ${certDerPath}`);
console.log('Keep rootCA.key.pem private. Anyone with it can mint trusted certificates on this machine.');