first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};
Generated Vendored Executable
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const node_fs_1 = require("node:fs");
const promises_1 = require("node:fs/promises");
const node_path_1 = require("node:path");
const mkcert_1 = require("./mkcert");
commander_1.program
.command("create-ca")
.option("--organization [value]", "organization name", "Test CA")
.option("--country-code [value]", "country code", "US")
.option("--state [value]", "state name", "California")
.option("--locality [value]", "locality address", "San Francisco")
.addOption(new commander_1.Option("--validity [days]", "validity in days")
.default(365)
.argParser((val) => Number.parseInt(val, 10)))
.option("--key [file]", "output key file", "ca.key")
.option("--cert [file]", "output certificate file", "ca.crt")
.action(async (options) => {
const ca = await (0, mkcert_1.createCA)(options);
await (0, promises_1.writeFile)(options.key, ca.key);
console.log(`CA Private Key: ${options.key}`);
await (0, promises_1.writeFile)(options.cert, ca.cert);
console.log(`CA Certificate: ${options.cert}`);
});
commander_1.program
.command("create-cert")
.alias("create-certificate")
.option("--ca-key [file]", "ca private key file", "ca.key")
.option("--ca-cert [file]", "ca certificate file", "ca.crt")
.addOption(new commander_1.Option("--validity [days]", "validity in days")
.default(365)
.argParser((val) => Number.parseInt(val, 10)))
.option("--key [file]", "output key file", "cert.key")
.option("--cert [file]", "output certificate file", "cert.crt")
.option("--organization [value]", "optional organization name")
.option("--email [value]", "optional email address")
.option("--domains, --domain [values...]", "domains or ip addresses", ["localhost", "127.0.0.1"])
.action(async (options) => {
let ca = {
key: await (0, promises_1.readFile)(options.caKey, "utf-8").catch(() => void 0),
cert: await (0, promises_1.readFile)(options.caCert, "utf-8").catch(() => void 0)
};
if (!ca.key || !ca.cert) {
console.error("Unable to find CA key or certificate.");
console.error("Please run `mkcert create-ca` to create a new certificate authority.");
return;
}
const cert = await (0, mkcert_1.createCert)({
ca: { key: ca.key, cert: ca.cert },
domains: options.domain,
validity: options.validity,
organization: options.organization,
email: options.email
});
await (0, promises_1.writeFile)(options.key, cert.key);
console.log(`Private Key: ${options.key}`);
await (0, promises_1.writeFile)(options.cert, `${cert.cert}${ca.cert}`); // write full chain certificate
console.log(`Certificate: ${options.cert}`);
});
function getVersion() {
return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.resolve)(__dirname, "../package.json"), "utf-8")).version;
}
commander_1.program.version(getVersion()).parseAsync(process.argv);
+20
View File
@@ -0,0 +1,20 @@
export type Certificate = {
key: string;
cert: string;
};
export type CertificateAuthorityOptions = {
organization: string;
countryCode: string;
state: string;
locality: string;
validity: number;
};
export declare function createCA(options: CertificateAuthorityOptions): Promise<Certificate>;
export type CertificateOptions = {
domains: string[];
validity: number;
organization?: string;
email?: string;
ca: Certificate;
};
export declare function createCert(options: CertificateOptions): Promise<Certificate>;
+100
View File
@@ -0,0 +1,100 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCert = exports.createCA = void 0;
const node_forge_1 = require("node-forge");
const node_net_1 = __importDefault(require("node:net"));
const node_util_1 = require("node:util");
async function generateCert(options) {
const { subject, issuer, extensions, validity } = options;
const generateKeyPair = (0, node_util_1.promisify)(node_forge_1.pki.rsa.generateKeyPair.bind(node_forge_1.pki.rsa));
// create random serial number between between 50000 and 99999
const serial = Math.floor(Math.random() * 95000 + 50000).toString();
const keyPair = await generateKeyPair({ bits: 2048, workers: 4 });
const cert = node_forge_1.pki.createCertificate();
// serial number must be hex encoded
cert.serialNumber = Buffer.from(serial).toString("hex");
cert.publicKey = keyPair.publicKey;
cert.setSubject(subject);
cert.setIssuer(issuer);
cert.setExtensions(extensions);
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setDate(cert.validity.notAfter.getDate() + validity);
// sign the certificate with it's own
// private key if no separate signing key is provided
const signWith = options.signWith ? node_forge_1.pki.privateKeyFromPem(options.signWith) : keyPair.privateKey;
cert.sign(signWith, node_forge_1.md.sha256.create());
return {
key: node_forge_1.pki.privateKeyToPem(keyPair.privateKey),
cert: node_forge_1.pki.certificateToPem(cert)
};
}
async function createCA(options) {
// certificate Attributes: https://git.io/fptna
const attributes = [
{ name: "commonName", value: options.organization },
{ name: "countryName", value: options.countryCode },
{ name: "stateOrProvinceName", value: options.state },
{ name: "localityName", value: options.locality },
{ name: "organizationName", value: options.organization }
];
// required certificate extensions for a certificate authority
const extensions = [
{ name: "basicConstraints", cA: true, critical: true },
{ name: "keyUsage", keyCertSign: true, critical: true }
];
return await generateCert({
subject: attributes,
issuer: attributes,
extensions: extensions,
validity: options.validity
});
}
exports.createCA = createCA;
async function createCert(options) {
// certificate Attributes: https://git.io/fptna
const attributes = [
{ name: "commonName", value: options.domains[0] } // use the first address as common name
];
if (options.organization) {
attributes.push({ name: "organizationName", value: options.organization });
}
if (options.email) {
attributes.push({ name: "emailAddress", value: options.email });
}
// required certificate extensions for a tls certificate
const extensions = [
{ name: "basicConstraints", cA: false, critical: true },
{
name: "keyUsage",
digitalSignature: true,
keyEncipherment: true,
critical: true
},
{ name: "extKeyUsage", serverAuth: true, clientAuth: true },
{
name: "subjectAltName",
altNames: options.domains.map((domain) => {
// types https://git.io/fptng
const TYPE_DOMAIN = 2;
const TYPE_IP = 7;
if (node_net_1.default.isIP(domain)) {
return { type: TYPE_IP, ip: domain };
}
return { type: TYPE_DOMAIN, value: domain };
})
}
];
const ca = node_forge_1.pki.certificateFromPem(options.ca.cert);
return await generateCert({
subject: attributes,
issuer: ca.subject.attributes,
extensions: extensions,
validity: options.validity,
signWith: options.ca.key
});
}
exports.createCert = createCert;