import {readFile, open} from "fs/promises" import enquirer from "enquirer" import {createPrivateKey, createSign} from "crypto" import chalk from "chalk" import {algorithm, signatureGuardEnd, signatureGuardStart} from "./signing-common.mjs" const {Invisible} = enquirer async function getPassword() { return await new Invisible({ message: "Enter the passphrase for smva-indexer-release.key.pem:" }).run() } async function decryptSecretKey(keyPath) { return createPrivateKey({ key: await readFile(keyPath), passphrase: await getPassword() }) } async function signBundle(bundlePath, destinationPath, keyPath) { const bundle = await readFile(bundlePath) if (!bundle.subarray(0, signatureGuardStart.length).equals(signatureGuardStart)) { throw new Error("No placeholder for the signature guard start found") } const signatureLength = bundle.subarray(signatureGuardStart.length).indexOf(signatureGuardEnd) if (signatureLength === -1) { throw new Error("No placeholder for the signature guard end found") } const sign = createSign(algorithm) const signedContent = bundle.subarray(signatureGuardStart.length + signatureLength + signatureGuardEnd.length) const secretKey = await decryptSecretKey(keyPath) sign.update(signedContent) const signature = sign.sign(secretKey, 'base64') let destination try { destination = await open(destinationPath, "w") await destination.write(signatureGuardStart) await destination.write(signature, null, "utf-8") await destination.write(signatureGuardEnd) await destination.write(signedContent) } finally { await destination?.close() } } async function main() { const [bundlePath, destinationPath, keyPath] = process.argv.slice(2) if (!bundlePath || !destinationPath || !keyPath) { process.stderr.write(chalk.red("Required arguments: bundlePath destinationPath keyPath\n")) process.exit(1) } try { await signBundle(bundlePath, destinationPath, keyPath) process.stderr.write(chalk.cyan(`Successfully signed ${chalk.cyanBright.bold(bundlePath)} as ${chalk.cyanBright.bold(destinationPath)} with ${chalk.cyanBright.bold(keyPath)}\n`)) } catch (ex) { process.stderr.write(chalk.red(`Failed to sign ${chalk.redBright.bold(bundlePath)} as ${chalk.redBright.bold(destinationPath)} with ${chalk.redBright.bold(keyPath)}: ${chalk.redBright.bold(ex)}\n`)) } } if (!global.main) { global.main = true main() }