{"version":3,"sources":["../../../bin/keypair.ts","../../../crypto.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// This script generates an RSA key pair and encrypts the private key using GPG with a symmetric key.\n// You must have the 'gpg' command-line tool installed on your system.\n// (e.g., `brew install gpg` on macOS, `sudo apt-get install gnupg` on Debian/Ubuntu).\n\nimport { Command } from 'commander'\nimport { stat, writeFile } from 'fs/promises'\nimport { extname, resolve } from 'path'\nimport prompts from 'prompts'\n\nimport { KeyObject, webcrypto as crypto } from 'crypto'\nimport { CIPHER_ALGORITHM, RSA_ALGORITHM, RSA_HASH } from '../crypto'\n\nimport { config as dotenvConfig } from 'dotenv'\ndotenvConfig({ quiet: true, override: true })\n\nconst program = new Command()\nprogram\n  .description('A script to generate and store an RSA key pair in an encrypted file.')\n  .option('-p, --public <path>', 'Path for the public key file', 'public.json')\n  .option('--private <path>', 'Path for the encrypted private key .pem', 'private.pem')\n  .option('-r, --replace', 'Replace existing files', false)\n  .parse(process.argv)\nconst options = program.opts()\n\nasync function main() {\n  try {\n    const publicKeyPath = resolve(options.public)\n    const encryptedKeyPath = resolve(options.private)\n\n    if (!extname(publicKeyPath).match(/^\\.(cjs|mjs|ts|json)$/)) {\n      console.error('Public key file must have .json, .cjs, .mjs or .ts extension.')\n      process.exit(1)\n    }\n    if (!encryptedKeyPath.endsWith('.pem')) {\n      console.error('Encrypted key file must have a .pem extension.')\n      process.exit(1)\n    }\n\n    const fileExists = async (path: string) => {\n      try {\n        await stat(path)\n        return true\n      }\n      catch (e: any) {\n        if (e.code === 'ENOENT') {\n          return false\n        }\n        throw e\n      }\n    }\n\n    if (await fileExists(publicKeyPath) && !options.replace) {\n      console.error(`Will not overwrite existing public key file: ${publicKeyPath}`)\n      process.exit(1)\n    }\n    if (await fileExists(encryptedKeyPath) && !options.replace) {\n      console.error(`Will not overwrite existing encrypted key file: ${encryptedKeyPath}`)\n      process.exit(1)\n    }\n\n    const { privateKey, publicKey } = await crypto.subtle.generateKey(\n      {\n        name: RSA_ALGORITHM,\n        modulusLength: 2048,\n        publicExponent: new Uint8Array([1, 0, 1]),\n        hash: RSA_HASH,\n      },\n      true, // extractable\n      ['encrypt', 'decrypt'],\n    )\n\n    const publicKeyJwk = await crypto.subtle.exportKey('jwk', publicKey)\n    switch (extname(options.public)) {\n      case '.json':\n        await writeFile(options.public, JSON.stringify(publicKeyJwk, null, 2))\n        break\n      case '.mjs':\n        await writeFile(options.public, `export const jwk = ${JSON.stringify(publicKeyJwk, null, 2)}`)\n        break\n      case '.cjs':\n        await writeFile(options.public, `module.exports.jwk = ${JSON.stringify(publicKeyJwk, null, 2)}`)\n        break\n      case '.ts':\n        await writeFile(options.public, `export const jwk: JsonWebKey = ${JSON.stringify(publicKeyJwk, null, 2)}`)\n        break\n    }\n\n    const { passphrase } = await prompts({\n      type: 'password',\n      name: 'passphrase',\n      message: 'Enter a passphrase to encrypt your private key:',\n    })\n\n    const privateKeyObject = KeyObject.from(privateKey)\n    const encryptedPkcs8Pem = privateKeyObject.export({\n      format: 'pem',\n      type: 'pkcs8',\n      cipher: CIPHER_ALGORITHM,\n      passphrase,\n    })\n    await writeFile(options.private, encryptedPkcs8Pem)\n  }\n  catch (error) {\n    if (error instanceof Error) {\n      console.error('An error occurred:', error.message)\n    }\n    else {\n      console.error('An unknown error occurred:', error)\n    }\n    process.exit(1)\n  }\n}\n\nmain()\n","export const KEYTYPE = 'RSA'\nexport const KEY_WRAPPING_ALG = 'RSA-OAEP-256'\nexport const CONTENT_ENCRYPTION_ALG = 'A256GCM'\nexport const RSA_HASH = 'SHA-256'\nexport const RSA_ALGORITHM = 'RSA-OAEP'\nexport const CIPHER_ALGORITHM = 'aes256'\nexport const AES_KEY_LENGTH = 256\n// export const AES_KEY_BYTES = 32\n\n// export const AES_ALGORITHM = 'AES-GCM'\n// export const IV_LENGTH = 12\n"],"mappings":"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","names":["dotenvConfig","crypto","prompts"]}