@sebastienrousseau/crypto-cli 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +325 -3
  2. package/dist/cli.js +37 -196
  3. package/dist/commands/decrypt.command.js +2 -2
  4. package/dist/commands/encrypt.command.js +2 -2
  5. package/dist/commands/generate.command.js +2 -2
  6. package/dist/commands/modern/cbom.command.d.ts +2 -1
  7. package/dist/commands/modern/cbom.command.d.ts.map +1 -1
  8. package/dist/commands/modern/cbom.command.js +99 -146
  9. package/dist/commands/modern/cbom.core.d.ts +5 -0
  10. package/dist/commands/modern/cbom.core.d.ts.map +1 -0
  11. package/dist/commands/modern/cbom.core.js +57 -0
  12. package/dist/commands/modern/encrypt.command.d.ts.map +1 -1
  13. package/dist/commands/modern/encrypt.command.js +42 -63
  14. package/dist/commands/modern/hash.command.d.ts.map +1 -1
  15. package/dist/commands/modern/hash.command.js +1 -1
  16. package/dist/commands/modern/keygen.command.js +1 -1
  17. package/dist/commands/modern/password-hash.command.d.ts.map +1 -1
  18. package/dist/commands/modern/password-hash.command.js +28 -27
  19. package/dist/commands/modern/sign.command.d.ts.map +1 -1
  20. package/dist/commands/modern/sign.command.js +83 -73
  21. package/dist/commands/reformat.command.js +2 -2
  22. package/dist/commands/revoke.command.js +2 -2
  23. package/dist/commands/session.command.js +2 -2
  24. package/dist/commands/sign.command.js +2 -2
  25. package/dist/commands/verify.command.js +2 -2
  26. package/dist/menu.d.ts +12 -0
  27. package/dist/menu.d.ts.map +1 -0
  28. package/dist/menu.js +107 -0
  29. package/dist/program/cbom.d.ts +4 -0
  30. package/dist/program/cbom.d.ts.map +1 -0
  31. package/dist/program/cbom.js +49 -0
  32. package/dist/program/encrypt.d.ts +6 -0
  33. package/dist/program/encrypt.d.ts.map +1 -0
  34. package/dist/program/encrypt.js +73 -0
  35. package/dist/program/hash.d.ts +4 -0
  36. package/dist/program/hash.d.ts.map +1 -0
  37. package/dist/program/hash.js +21 -0
  38. package/dist/program/index.d.ts +7 -0
  39. package/dist/program/index.d.ts.map +1 -0
  40. package/dist/program/index.js +69 -0
  41. package/dist/program/io.d.ts +35 -0
  42. package/dist/program/io.d.ts.map +1 -0
  43. package/dist/program/io.js +65 -0
  44. package/dist/program/keygen.d.ts +4 -0
  45. package/dist/program/keygen.d.ts.map +1 -0
  46. package/dist/program/keygen.js +32 -0
  47. package/dist/program/password.d.ts +4 -0
  48. package/dist/program/password.d.ts.map +1 -0
  49. package/dist/program/password.js +73 -0
  50. package/dist/program/secrets.d.ts +30 -0
  51. package/dist/program/secrets.d.ts.map +1 -0
  52. package/dist/program/secrets.js +70 -0
  53. package/dist/program/sign.d.ts +18 -0
  54. package/dist/program/sign.d.ts.map +1 -0
  55. package/dist/program/sign.js +130 -0
  56. package/dist/program/usage.d.ts +7 -0
  57. package/dist/program/usage.d.ts.map +1 -0
  58. package/dist/program/usage.js +36 -0
  59. package/package.json +28 -36
@@ -49,83 +49,93 @@ const ALGORITHMS = [
49
49
  "ml-dsa-65",
50
50
  "ml-dsa-87",
51
51
  ];
52
- const handleModernSign = async () => {
53
- const response = await (0, prompts_1.default)([
54
- {
55
- type: "select",
56
- name: "algorithm",
57
- message: "Select signing algorithm",
58
- choices: ALGORITHMS.map((a) => ({ title: a, value: a })),
59
- },
60
- {
61
- type: "select",
62
- name: "action",
63
- message: "Action",
64
- choices: [
65
- { title: "Generate key pair + sign", value: "keygen-sign" },
66
- { title: "Sign with existing key", value: "sign" },
67
- { title: "Verify signature", value: "verify" },
68
- ],
69
- },
70
- {
71
- type: "text",
72
- name: "message",
73
- message: "Message to sign/verify",
74
- },
52
+ const QUESTIONS = [
53
+ {
54
+ type: "select",
55
+ name: "algorithm",
56
+ message: "Select signing algorithm",
57
+ choices: ALGORITHMS.map((a) => ({ title: a, value: a })),
58
+ },
59
+ {
60
+ type: "select",
61
+ name: "action",
62
+ message: "Action",
63
+ choices: [
64
+ { title: "Generate key pair + sign", value: "keygen-sign" },
65
+ { title: "Sign with existing key", value: "sign" },
66
+ { title: "Verify signature", value: "verify" },
67
+ ],
68
+ },
69
+ {
70
+ type: "text",
71
+ name: "message",
72
+ message: "Message to sign/verify",
73
+ },
74
+ ];
75
+ const KEYGEN_ALGORITHM = {
76
+ "ecdsa-p256": "p256",
77
+ "ecdsa-p384": "p384",
78
+ };
79
+ function printJson(value) {
80
+ write_utils_1.writeUtils.writeLn(kleur_1.default.green(JSON.stringify(value, null, 2)));
81
+ }
82
+ async function keygenAndSign(crypto, algorithm, message) {
83
+ if (algorithm === "schnorr") {
84
+ const { generateSchnorrKeyPair } = await Promise.resolve().then(() => __importStar(require("@sebastienrousseau/crypto-lib/modern")));
85
+ const kp = generateSchnorrKeyPair();
86
+ const sig = crypto.sign("schnorr", kp.privateKey, message);
87
+ printJson({
88
+ publicKey: kp.publicKey,
89
+ privateKey: kp.privateKey,
90
+ signature: sig,
91
+ algorithm: "schnorr",
92
+ });
93
+ return;
94
+ }
95
+ const { generateKeyPair } = await Promise.resolve().then(() => __importStar(require("@sebastienrousseau/crypto-lib/keys")));
96
+ const keyAlgo = KEYGEN_ALGORITHM[algorithm] ?? algorithm;
97
+ const kp = generateKeyPair(keyAlgo);
98
+ const sig = crypto.sign(algorithm, kp.privateKey, message);
99
+ printJson({
100
+ publicKey: kp.publicKey,
101
+ privateKey: kp.privateKey,
102
+ signature: sig,
103
+ algorithm,
104
+ });
105
+ }
106
+ async function signWithKey(crypto, algorithm, message) {
107
+ const keyResp = await (0, prompts_1.default)({
108
+ type: "password",
109
+ name: "privateKey",
110
+ message: "Private key (hex)",
111
+ });
112
+ if (!keyResp.privateKey)
113
+ return;
114
+ const sig = crypto.sign(algorithm, keyResp.privateKey, message);
115
+ printJson({ signature: sig, algorithm });
116
+ }
117
+ async function verifySignature(crypto, algorithm, message) {
118
+ const verifyResp = await (0, prompts_1.default)([
119
+ { type: "text", name: "publicKey", message: "Public key (hex)" },
120
+ { type: "text", name: "signature", message: "Signature (hex)" },
75
121
  ]);
122
+ if (!verifyResp.publicKey || !verifyResp.signature)
123
+ return;
124
+ const valid = crypto.verify(algorithm, verifyResp.publicKey, message, verifyResp.signature);
125
+ printJson({ valid, algorithm });
126
+ }
127
+ const handleModernSign = async () => {
128
+ const response = await (0, prompts_1.default)(QUESTIONS);
76
129
  if (!response.algorithm || !response.action || !response.message)
77
130
  return;
78
131
  try {
79
- const { crypto } = await Promise.resolve().then(() => __importStar(require("@sebastienrousseau/crypto-lib/dist/crypto")));
80
- if (response.action === "keygen-sign") {
81
- const { generateKeyPair } = await Promise.resolve().then(() => __importStar(require("@sebastienrousseau/crypto-lib/dist/keys/keygen")));
82
- let keyAlgo = response.algorithm;
83
- if (keyAlgo === "ecdsa-p256")
84
- keyAlgo = "p256";
85
- if (keyAlgo === "ecdsa-p384")
86
- keyAlgo = "p384";
87
- if (keyAlgo === "schnorr") {
88
- const { generateSchnorrKeyPair } = await Promise.resolve().then(() => __importStar(require("@sebastienrousseau/crypto-lib/dist/modern/curves")));
89
- const kp = generateSchnorrKeyPair();
90
- const sig = crypto.sign("schnorr", kp.privateKey, response.message);
91
- write_utils_1.writeUtils.writeLn(kleur_1.default.green(JSON.stringify({
92
- publicKey: kp.publicKey,
93
- privateKey: kp.privateKey,
94
- signature: sig,
95
- algorithm: "schnorr",
96
- }, null, 2)));
97
- return;
98
- }
99
- const kp = generateKeyPair(keyAlgo);
100
- const sig = crypto.sign(response.algorithm, kp.privateKey, response.message);
101
- write_utils_1.writeUtils.writeLn(kleur_1.default.green(JSON.stringify({
102
- publicKey: kp.publicKey,
103
- privateKey: kp.privateKey,
104
- signature: sig,
105
- algorithm: response.algorithm,
106
- }, null, 2)));
107
- }
108
- else if (response.action === "sign") {
109
- const keyResp = await (0, prompts_1.default)({
110
- type: "password",
111
- name: "privateKey",
112
- message: "Private key (hex)",
113
- });
114
- if (!keyResp.privateKey)
115
- return;
116
- const sig = crypto.sign(response.algorithm, keyResp.privateKey, response.message);
117
- write_utils_1.writeUtils.writeLn(kleur_1.default.green(JSON.stringify({ signature: sig, algorithm: response.algorithm }, null, 2)));
118
- }
119
- else {
120
- const verifyResp = await (0, prompts_1.default)([
121
- { type: "text", name: "publicKey", message: "Public key (hex)" },
122
- { type: "text", name: "signature", message: "Signature (hex)" },
123
- ]);
124
- if (!verifyResp.publicKey || !verifyResp.signature)
125
- return;
126
- const valid = crypto.verify(response.algorithm, verifyResp.publicKey, response.message, verifyResp.signature);
127
- write_utils_1.writeUtils.writeLn(kleur_1.default.green(JSON.stringify({ valid, algorithm: response.algorithm }, null, 2)));
128
- }
132
+ const { crypto } = await Promise.resolve().then(() => __importStar(require("@sebastienrousseau/crypto-lib")));
133
+ let run = verifySignature;
134
+ if (response.action === "keygen-sign")
135
+ run = keygenAndSign;
136
+ else if (response.action === "sign")
137
+ run = signWithKey;
138
+ await run(crypto, response.algorithm, response.message);
129
139
  }
130
140
  catch (err) {
131
141
  write_utils_1.writeUtils.writeLn(kleur_1.default.red(`Operation failed: ${err.message}`));
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const reformat_1 = __importDefault(require("@sebastienrousseau/crypto-lib/dist/lib/reformat"));
6
+ const pgp_1 = require("@sebastienrousseau/crypto-lib/pgp");
7
7
  const prompts_1 = __importDefault(require("prompts"));
8
8
  const handleReformat = async () => {
9
9
  const responseReformat = await (0, prompts_1.default)([
@@ -49,7 +49,7 @@ const handleReformat = async () => {
49
49
  console.error("\n🔔 You must provide a value for each of the properties.\n");
50
50
  }
51
51
  else {
52
- await (0, reformat_1.default)(data);
52
+ await (0, pgp_1.reformat)(data);
53
53
  }
54
54
  };
55
55
  exports.default = handleReformat;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const revoke_1 = __importDefault(require("@sebastienrousseau/crypto-lib/dist/lib/revoke"));
6
+ const pgp_1 = require("@sebastienrousseau/crypto-lib/pgp");
7
7
  const prompts_1 = __importDefault(require("prompts"));
8
8
  const handleRevoke = async () => {
9
9
  const responseRevoke = await (0, prompts_1.default)([
@@ -33,7 +33,7 @@ const handleRevoke = async () => {
33
33
  console.error("\n🔔 You must provide a value for each of the properties.\n");
34
34
  }
35
35
  else {
36
- await (0, revoke_1.default)(data);
36
+ await (0, pgp_1.revoke)(data);
37
37
  }
38
38
  };
39
39
  exports.default = handleRevoke;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const session_1 = __importDefault(require("@sebastienrousseau/crypto-lib/dist/lib/session"));
6
+ const pgp_1 = require("@sebastienrousseau/crypto-lib/pgp");
7
7
  const prompts_1 = __importDefault(require("prompts"));
8
8
  const handleSession = async () => {
9
9
  const responseSession = await (0, prompts_1.default)([
@@ -35,7 +35,7 @@ const handleSession = async () => {
35
35
  }
36
36
  else {
37
37
  console.log(data);
38
- await (0, session_1.default)(data);
38
+ await (0, pgp_1.session)(data);
39
39
  }
40
40
  };
41
41
  exports.default = handleSession;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const sign_1 = __importDefault(require("@sebastienrousseau/crypto-lib/dist/lib/sign"));
6
+ const pgp_1 = require("@sebastienrousseau/crypto-lib/pgp");
7
7
  const prompts_1 = __importDefault(require("prompts"));
8
8
  const handleSign = async () => {
9
9
  const responseSign = await (0, prompts_1.default)([
@@ -42,7 +42,7 @@ const handleSign = async () => {
42
42
  console.error("\n🔔 You must provide a value for each of the properties.\n");
43
43
  }
44
44
  else {
45
- await (0, sign_1.default)(data);
45
+ await (0, pgp_1.sign)(data);
46
46
  }
47
47
  };
48
48
  exports.default = handleSign;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const verify_1 = __importDefault(require("@sebastienrousseau/crypto-lib/dist/lib/verify"));
6
+ const pgp_1 = require("@sebastienrousseau/crypto-lib/pgp");
7
7
  const prompts_1 = __importDefault(require("prompts"));
8
8
  const handleVerify = async () => {
9
9
  const responseVerify = await (0, prompts_1.default)([
@@ -35,7 +35,7 @@ const handleVerify = async () => {
35
35
  }
36
36
  else {
37
37
  console.log(data);
38
- await (0, verify_1.default)(data);
38
+ await (0, pgp_1.verify)(data);
39
39
  }
40
40
  };
41
41
  exports.default = handleVerify;
package/dist/menu.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { Command } from "./commands/index";
2
+ type Handler = keyof typeof Command;
3
+ export interface MenuEntry {
4
+ title: string;
5
+ description: string;
6
+ heading: string;
7
+ handler: Handler;
8
+ }
9
+ export declare const menuEntries: () => MenuEntry[];
10
+ export declare const runMenu: () => Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAM3C,KAAK,OAAO,GAAG,MAAM,OAAO,OAAO,CAAC;AAGpC,MAAM,WAAW,SAAS;IAExB,KAAK,EAAE,MAAM,CAAC;IAEd,WAAW,EAAE,MAAM,CAAC;IAEpB,OAAO,EAAE,MAAM,CAAC;IAEhB,OAAO,EAAE,OAAO,CAAC;CAClB;AA0DD,eAAO,MAAM,WAAW,QAAO,SAAS,EAcvC,CAAC;AAMF,eAAO,MAAM,OAAO,QAAa,OAAO,CAAC,IAAI,CA8B5C,CAAC"}
package/dist/menu.js ADDED
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runMenu = exports.menuEntries = void 0;
7
+ const kleur_1 = __importDefault(require("kleur"));
8
+ const prompts_1 = __importDefault(require("prompts"));
9
+ const index_1 = require("./commands/index");
10
+ const index_2 = require("./constants/index");
11
+ const banner_1 = require("./helpers/banner");
12
+ const write_utils_1 = require("./utils/write.utils");
13
+ const LEGACY = [
14
+ [1, "handleGenerate"],
15
+ [2, "handleEncrypt"],
16
+ [3, "handleDecrypt"],
17
+ [4, "handleReformat"],
18
+ [5, "handleRevoke"],
19
+ [6, "handleSession"],
20
+ [7, "handleSign"],
21
+ [8, "handleVerify"],
22
+ ];
23
+ const MODERN = [
24
+ {
25
+ title: "Modern Keygen",
26
+ description: "Generate keys (Ed25519, ML-DSA, ML-KEM, P-256, etc.)",
27
+ heading: "Modern Key Generation",
28
+ handler: "handleModernKeygen",
29
+ },
30
+ {
31
+ title: "Modern Hash",
32
+ description: "Hash data (SHA-2, SHA-3, BLAKE2b, BLAKE3)",
33
+ heading: "Modern Hashing",
34
+ handler: "handleModernHash",
35
+ },
36
+ {
37
+ title: "Modern Encrypt",
38
+ description: "Encrypt (XChaCha20, AES-GCM, AES-GCM-SIV)",
39
+ heading: "Modern Encryption",
40
+ handler: "handleModernEncrypt",
41
+ },
42
+ {
43
+ title: "Modern Sign",
44
+ description: "Sign/verify (Ed25519, ECDSA, Schnorr, ML-DSA)",
45
+ heading: "Modern Signing",
46
+ handler: "handleModernSign",
47
+ },
48
+ {
49
+ title: "Password Hash",
50
+ description: "Hash/verify passwords (Argon2id/i/d)",
51
+ heading: "Password Hashing (Argon2)",
52
+ handler: "handlePasswordHash",
53
+ },
54
+ {
55
+ title: "CBOM",
56
+ description: "Generate or audit Cryptographic Bill of Materials",
57
+ heading: "Cryptographic Bill of Materials (CBOM)",
58
+ handler: "handleModernCbom",
59
+ },
60
+ ];
61
+ const menuEntries = () => [
62
+ ...LEGACY.map(([n, handler]) => ({
63
+ title: index_2.constants[`CLI_FN_${n}_TTL`],
64
+ description: index_2.constants[`CLI_FN_${n}_DES`],
65
+ heading: index_2.constants.CLI_HDL_1_DES,
66
+ handler,
67
+ })),
68
+ ...MODERN,
69
+ {
70
+ title: index_2.constants.CLI_FN_9_TTL,
71
+ description: index_2.constants.CLI_FN_9_DES,
72
+ heading: index_2.constants.CLI_FN_9_TTL,
73
+ handler: "handleHelp",
74
+ },
75
+ ];
76
+ exports.menuEntries = menuEntries;
77
+ const runMenu = async () => {
78
+ (0, index_2.language)(index_2.locale);
79
+ console.clear();
80
+ (0, banner_1.welcome)(index_2.constants.CLI_TITLE);
81
+ write_utils_1.writeUtils.writeLn(index_2.constants.CLI_TITLE);
82
+ write_utils_1.writeUtils.writeLn("");
83
+ write_utils_1.writeUtils.writeLn(index_2.constants.CLI_DESCRIPTION);
84
+ write_utils_1.writeUtils.writeLn("");
85
+ const entries = (0, exports.menuEntries)();
86
+ const response = await (0, prompts_1.default)({
87
+ type: "select",
88
+ name: index_2.constants.PROMPT_SELECT_TTL,
89
+ message: index_2.constants.PROMPT_SELECT_DES + "\n\n",
90
+ choices: entries.map(({ title, description }) => ({
91
+ title,
92
+ description,
93
+ value: title,
94
+ })),
95
+ });
96
+ const selected = response[index_2.constants.PROMPT_SELECT_TTL];
97
+ const entry = entries.find((e) => e.title === selected);
98
+ write_utils_1.writeUtils.writeLn("");
99
+ if (!entry) {
100
+ write_utils_1.writeUtils.writeLn(kleur_1.default.red(index_2.constants.CLI_ERR_1));
101
+ return;
102
+ }
103
+ write_utils_1.writeUtils.writeLn(kleur_1.default.green(entry.heading));
104
+ await index_1.Command[entry.handler]();
105
+ };
106
+ exports.runMenu = runMenu;
107
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ import { type RunContext } from "./io";
3
+ export declare const registerCbom: (program: Command, ctx: RunContext) => Command;
4
+ //# sourceMappingURL=cbom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbom.d.ts","sourceRoot":"","sources":["../../src/program/cbom.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAO5C,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAiF9D,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,EAAE,KAAK,UAAU,YAQ7D,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerCbom = void 0;
4
+ const promises_1 = require("node:fs/promises");
5
+ const commander_1 = require("commander");
6
+ const cbom_core_1 = require("../commands/modern/cbom.core");
7
+ const io_1 = require("./io");
8
+ const deliver = async (ctx, document, opts, label) => {
9
+ const pretty = JSON.stringify(document, null, 2);
10
+ if (opts.output === undefined) {
11
+ (0, io_1.emit)(ctx.io, Boolean(opts.json), document, pretty);
12
+ return;
13
+ }
14
+ await (0, promises_1.writeFile)(opts.output, `${pretty}\n`, "utf8");
15
+ ctx.io.stderr(`${label} written to ${opts.output}\n`);
16
+ };
17
+ const withOutputOptions = (command, what) => command
18
+ .option("-o, --output <file>", `write the ${what} to a file, not stdout`)
19
+ .option("--json", `print the ${what} as one line of JSON`);
20
+ const registerScan = (cbom, ctx) => withOutputOptions(cbom
21
+ .command("scan")
22
+ .description("Scan source code and print its CBOM")
23
+ .argument("[directory]", "directory or file to scan", ".")
24
+ .addOption(new commander_1.Option("-f, --format <format>", "CBOM standard")
25
+ .choices(cbom_core_1.CBOM_FORMATS)
26
+ .default("cyclonedx")), "CBOM").action(async (directory, opts) => {
27
+ await deliver(ctx, await (0, cbom_core_1.buildCbom)(directory, opts.format), opts, "CBOM");
28
+ });
29
+ const registerAudit = (cbom, ctx) => withOutputOptions(cbom
30
+ .command("audit")
31
+ .description("Validate and audit a CBOM; exits 1 when the audit status is FAIL")
32
+ .argument("[file]", "CBOM JSON file; '-' or omitted reads standard input"), "audit report").action(async (file, opts) => {
33
+ const raw = (await (0, io_1.readInput)(file, ctx.io)).toString("utf8");
34
+ const result = await (0, cbom_core_1.auditCbomJson)(raw);
35
+ await deliver(ctx, result, opts, "Audit report");
36
+ if (result.status === "FAIL")
37
+ ctx.exitCode = io_1.EXIT.FAILURE;
38
+ });
39
+ const registerCbom = (program, ctx) => {
40
+ const cbom = program
41
+ .command("cbom")
42
+ .description("Generate or audit a Cryptographic Bill of Materials")
43
+ .helpCommand(false);
44
+ registerScan(cbom, ctx);
45
+ registerAudit(cbom, ctx);
46
+ return cbom;
47
+ };
48
+ exports.registerCbom = registerCbom;
49
+ //# sourceMappingURL=cbom.js.map
@@ -0,0 +1,6 @@
1
+ import { Command } from "commander";
2
+ import { type RunContext } from "./io";
3
+ export declare const parseSymmetricKey: (raw: Buffer) => Uint8Array;
4
+ export declare const registerEncrypt: (program: Command, ctx: RunContext) => Command;
5
+ export declare const registerDecrypt: (program: Command, ctx: RunContext) => Command;
6
+ //# sourceMappingURL=encrypt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt.d.ts","sourceRoot":"","sources":["../../src/program/encrypt.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,MAAM,CAAC;AA6Bd,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,KAAG,UAQ/C,CAAC;AAgEF,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,EAAE,KAAK,UAAU,YAU7D,CAAC;AASL,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,EAAE,KAAK,UAAU,YA+B7D,CAAC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerDecrypt = exports.registerEncrypt = exports.parseSymmetricKey = void 0;
4
+ const high_level_1 = require("@sebastienrousseau/crypto-lib/high-level");
5
+ const io_1 = require("./io");
6
+ const secrets_1 = require("./secrets");
7
+ const KEY_LENGTH = 32;
8
+ const HEX_KEY = /^[0-9a-fA-F]{64}$/;
9
+ const BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
10
+ const parseSymmetricKey = (raw) => {
11
+ const text = raw.toString("latin1").trim();
12
+ if (HEX_KEY.test(text))
13
+ return Buffer.from(text, "hex");
14
+ if (raw.length === KEY_LENGTH)
15
+ return raw;
16
+ throw new Error(`the key must be ${KEY_LENGTH} bytes: 64 hexadecimal characters ` +
17
+ `or ${KEY_LENGTH} raw bytes`);
18
+ };
19
+ exports.parseSymmetricKey = parseSymmetricKey;
20
+ const readKey = async (ctx, opts, file) => {
21
+ const source = { file: opts.keyFile, stdin: opts.keyStdin };
22
+ const raw = await (0, secrets_1.requireSecret)({
23
+ io: ctx.io,
24
+ source,
25
+ flags: secrets_1.KEY_FLAGS,
26
+ dataOnStdin: (0, io_1.isStdin)(file),
27
+ checkMode: true,
28
+ }, "key");
29
+ return (0, exports.parseSymmetricKey)(raw);
30
+ };
31
+ const parseSealed = (input) => {
32
+ const sealed = (0, io_1.valueOrJsonField)(input, "sealed");
33
+ if (!BASE64.test(sealed)) {
34
+ throw new Error("the input is not base64 from crypto-cli encrypt");
35
+ }
36
+ return Buffer.from(sealed, "base64");
37
+ };
38
+ const secretboxCommand = (program, name, description, input) => (0, secrets_1.withSecretOptions)(program
39
+ .command(name)
40
+ .description(description)
41
+ .argument("[file]", `${input}; '-' or omitted reads standard input`), secrets_1.KEY_FLAGS, {
42
+ what: "key",
43
+ format: "32 bytes, as 64 hex characters or raw",
44
+ takesData: true,
45
+ }).option("--json", "print the result as one line of JSON");
46
+ const registerEncrypt = (program, ctx) => secretboxCommand(program, "encrypt", "Encrypt with XChaCha20-Poly1305 and print the sealed box as base64", "file to encrypt").action(async (file, opts) => {
47
+ const key = await readKey(ctx, opts, file);
48
+ const result = high_level_1.secretbox.seal(key, await (0, io_1.readInput)(file, ctx.io));
49
+ (0, io_1.emit)(ctx.io, Boolean(opts.json), result, result.sealed);
50
+ });
51
+ exports.registerEncrypt = registerEncrypt;
52
+ const registerDecrypt = (program, ctx) => secretboxCommand(program, "decrypt", "Decrypt the output of encrypt; exits 1 on a wrong key or modified input", "output of encrypt (base64 or its --json line)").action(async (file, opts) => {
53
+ const key = await readKey(ctx, opts, file);
54
+ const sealed = parseSealed(await (0, io_1.readInput)(file, ctx.io));
55
+ let plaintext;
56
+ try {
57
+ plaintext = high_level_1.secretbox.open(key, sealed);
58
+ }
59
+ catch {
60
+ throw new Error("decryption failed: wrong key, or the input was modified or truncated");
61
+ }
62
+ if (!opts.json) {
63
+ ctx.io.stdout(plaintext);
64
+ return;
65
+ }
66
+ (0, io_1.emit)(ctx.io, true, {
67
+ plaintext: Buffer.from(plaintext).toString("base64"),
68
+ encoding: "base64",
69
+ algorithm: "xchacha20-poly1305",
70
+ }, "");
71
+ });
72
+ exports.registerDecrypt = registerDecrypt;
73
+ //# sourceMappingURL=encrypt.js.map
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ import { type RunContext } from "./io";
3
+ export declare const registerHash: (program: Command, ctx: RunContext) => Command;
4
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/program/hash.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAM5C,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAcxD,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,EAAE,KAAK,UAAU,YAexD,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerHash = void 0;
4
+ const commander_1 = require("commander");
5
+ const modern_1 = require("@sebastienrousseau/crypto-lib/modern");
6
+ const io_1 = require("./io");
7
+ const registerHash = (program, ctx) => program
8
+ .command("hash")
9
+ .description("Hash a file, or standard input when no file is given")
10
+ .argument("[file]", "file to hash; '-' or omitted reads standard input")
11
+ .addOption(new commander_1.Option("-a, --algorithm <name>", "hash algorithm")
12
+ .choices(modern_1.HASH_ALGORITHMS)
13
+ .default("sha256"))
14
+ .option("--json", "print the result as one line of JSON")
15
+ .action(async (file, opts) => {
16
+ const data = await (0, io_1.readInput)(file, ctx.io);
17
+ const result = (0, modern_1.hash)({ algorithm: opts.algorithm, data });
18
+ (0, io_1.emit)(ctx.io, Boolean(opts.json), result, result.digest);
19
+ });
20
+ exports.registerHash = registerHash;
21
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1,7 @@
1
+ import { Command } from "commander";
2
+ import { type CliIO, type RunContext } from "./io";
3
+ export { EXIT, exitOnClosedPipe, processIO, type CliIO, type RunContext, } from "./io";
4
+ export declare const buildProgram: (ctx: RunContext, version: string) => Command;
5
+ export declare const run: (args: string[], io: CliIO) => Promise<number>;
6
+ export declare const main: (args: string[], io: CliIO, menu: () => Promise<void>) => Promise<number>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/program/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAC;AAKpD,OAAO,EAAoB,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAKrE,OAAO,EACL,IAAI,EACJ,gBAAgB,EAChB,SAAS,EACT,KAAK,KAAK,EACV,KAAK,UAAU,GAChB,MAAM,MAAM,CAAC;AASd,eAAO,MAAM,YAAY,GAAI,KAAK,UAAU,EAAE,SAAS,MAAM,KAAG,OAqB/D,CAAC;AAmBF,eAAO,MAAM,GAAG,GAAU,MAAM,MAAM,EAAE,EAAE,IAAI,KAAK,KAAG,OAAO,CAAC,MAAM,CASnE,CAAC;AAWF,eAAO,MAAM,IAAI,GACf,MAAM,MAAM,EAAE,EACd,IAAI,KAAK,EACT,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,MAAM,CAShB,CAAC"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = exports.run = exports.buildProgram = exports.processIO = exports.exitOnClosedPipe = exports.EXIT = void 0;
4
+ const commander_1 = require("commander");
5
+ const version_utils_1 = require("../utils/version.utils");
6
+ const cbom_1 = require("./cbom");
7
+ const hash_1 = require("./hash");
8
+ const encrypt_1 = require("./encrypt");
9
+ const io_1 = require("./io");
10
+ const keygen_1 = require("./keygen");
11
+ const password_1 = require("./password");
12
+ const sign_1 = require("./sign");
13
+ var io_2 = require("./io");
14
+ Object.defineProperty(exports, "EXIT", { enumerable: true, get: function () { return io_2.EXIT; } });
15
+ Object.defineProperty(exports, "exitOnClosedPipe", { enumerable: true, get: function () { return io_2.exitOnClosedPipe; } });
16
+ Object.defineProperty(exports, "processIO", { enumerable: true, get: function () { return io_2.processIO; } });
17
+ const buildProgram = (ctx, version) => {
18
+ const program = new commander_1.Command("crypto-cli")
19
+ .description("Cryptographic operations from the command line. Run without " +
20
+ "arguments in a terminal for the interactive menu.")
21
+ .version(version, "-V, --version", "print the version")
22
+ .helpOption("-h, --help", "print help")
23
+ .helpCommand(false)
24
+ .exitOverride()
25
+ .configureOutput({ writeOut: ctx.io.stdout, writeErr: ctx.io.stderr })
26
+ .showSuggestionAfterError();
27
+ (0, hash_1.registerHash)(program, ctx);
28
+ (0, keygen_1.registerKeygen)(program, ctx);
29
+ (0, encrypt_1.registerEncrypt)(program, ctx);
30
+ (0, encrypt_1.registerDecrypt)(program, ctx);
31
+ (0, sign_1.registerSign)(program, ctx);
32
+ (0, sign_1.registerVerify)(program, ctx);
33
+ (0, password_1.registerPassword)(program, ctx);
34
+ (0, cbom_1.registerCbom)(program, ctx);
35
+ return program;
36
+ };
37
+ exports.buildProgram = buildProgram;
38
+ const exitCodeFor = (err, io) => {
39
+ if (err instanceof commander_1.CommanderError) {
40
+ return err.exitCode === 0 ? io_1.EXIT.OK : io_1.EXIT.USAGE;
41
+ }
42
+ io.stderr(`crypto-cli: ${err.message}\n`);
43
+ return err instanceof io_1.UsageError ? io_1.EXIT.USAGE : io_1.EXIT.FAILURE;
44
+ };
45
+ const run = async (args, io) => {
46
+ const ctx = { io, exitCode: io_1.EXIT.OK };
47
+ const program = (0, exports.buildProgram)(ctx, await (0, version_utils_1.getVersion)());
48
+ try {
49
+ await program.parseAsync(args, { from: "user" });
50
+ return ctx.exitCode;
51
+ }
52
+ catch (err) {
53
+ return exitCodeFor(err, io);
54
+ }
55
+ };
56
+ exports.run = run;
57
+ const main = async (args, io, menu) => {
58
+ if (args.length > 0)
59
+ return (0, exports.run)(args, io);
60
+ if (io.isTTY) {
61
+ await menu();
62
+ return io_1.EXIT.OK;
63
+ }
64
+ const ctx = { io, exitCode: io_1.EXIT.OK };
65
+ io.stderr((0, exports.buildProgram)(ctx, await (0, version_utils_1.getVersion)()).helpInformation());
66
+ return io_1.EXIT.USAGE;
67
+ };
68
+ exports.main = main;
69
+ //# sourceMappingURL=index.js.map