import { createHash, createPrivateKey, createPublicKey, generateKeyPairSync } from "node:crypto"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const defaultPrivatePath = path.join( process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), "forgeflow", "release-signing-private.pem", ); const privatePath = path.resolve(process.env.FORGEFLOW_UPDATE_SIGNING_PRIVATE_KEY || defaultPrivatePath); const publicPath = path.join(root, "build", "update-signing-public.pem"); let privateKey; try { privateKey = createPrivateKey(await readFile(privatePath)); if (privateKey.asymmetricKeyType !== "ed25519") throw new Error("The existing key is not Ed25519."); } catch (error) { if (error.code !== "ENOENT") throw error; privateKey = generateKeyPairSync("ed25519").privateKey; await mkdir(path.dirname(privatePath), { recursive: true, mode: 0o700 }); await writeFile(privatePath, privateKey.export({ type: "pkcs8", format: "pem" }), { mode: 0o600, flag: "wx" }); } const publicKey = createPublicKey(privateKey); const publicPem = publicKey.export({ type: "spki", format: "pem" }); await mkdir(path.dirname(publicPath), { recursive: true }); await writeFile(publicPath, publicPem, { mode: 0o644 }); const fingerprint = createHash("sha256").update(publicKey.export({ type: "spki", format: "der" })).digest("hex"); console.log(`ForgeFlow Ed25519 update key ready. Public key fingerprint: SHA256:${fingerprint}`); console.log(`Private key: ${privatePath}`); console.log(`Public key: ${publicPath}`);