wyvrnpm 2.12.3 → 2.13.12

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.
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const ed25519 = require('../signing/ed25519');
7
+ const log = require('../logger');
8
+
9
+ /**
10
+ * `wyvrnpm key gen --out <dir> [--id <publisher-id>]`
11
+ *
12
+ * Generates a fresh Ed25519 keypair and writes:
13
+ * <dir>/<id>.priv.pem — PKCS#8 private key (publisher keeps secret)
14
+ * <dir>/<id>.pub.pem — SPKI PEM public key (paste into trust anchor)
15
+ * <dir>/<id>.pub.b64 — Base64 SPKI DER (the literal value for keys.json)
16
+ *
17
+ * Refuses to overwrite existing files — rotation events are rare and
18
+ * destructive enough that the user should explicitly remove the old keys
19
+ * (or pick a fresh `--id`) rather than have the command stomp them.
20
+ */
21
+ async function gen(argv) {
22
+ const outDir = argv.out;
23
+ const id = argv.id ?? 'wyvrnpm';
24
+ if (!outDir) { log.error('--out <dir> is required'); process.exit(1); }
25
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(id)) {
26
+ log.error(`--id must match /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/ (got "${id}")`);
27
+ process.exit(1);
28
+ }
29
+
30
+ const privPath = path.join(outDir, `${id}.priv.pem`);
31
+ const pubPath = path.join(outDir, `${id}.pub.pem`);
32
+ const b64Path = path.join(outDir, `${id}.pub.b64`);
33
+
34
+ for (const p of [privPath, pubPath, b64Path]) {
35
+ if (fs.existsSync(p)) {
36
+ log.error(`refusing to overwrite existing file: ${p}`);
37
+ process.exit(1);
38
+ }
39
+ }
40
+
41
+ fs.mkdirSync(outDir, { recursive: true });
42
+ const k = ed25519.generateKeyPair();
43
+ // Private key permissions: chmod 0600 on POSIX so a stray process or
44
+ // backup tool doesn't accidentally include it. No-op on Windows.
45
+ fs.writeFileSync(privPath, k.privateKeyPem, { mode: 0o600 });
46
+ fs.writeFileSync(pubPath, k.publicKeyPem);
47
+ fs.writeFileSync(b64Path, k.publicKeyB64 + '\n');
48
+
49
+ if (argv.format === 'json') {
50
+ process.stdout.write(JSON.stringify({
51
+ command: 'key gen',
52
+ wyvrnpmVersion: require('../../package.json').version,
53
+ id,
54
+ out: outDir,
55
+ privateKeyFile: privPath,
56
+ publicKeyPem: pubPath,
57
+ publicKeyB64: b64Path,
58
+ publicKey: k.publicKeyB64,
59
+ }, null, 2) + '\n');
60
+ } else {
61
+ log.success(`Generated ed25519 keypair "${id}"`);
62
+ log.info(` private key : ${privPath}`);
63
+ log.info(` public PEM : ${pubPath}`);
64
+ log.info(` public b64 : ${b64Path}`);
65
+ console.log();
66
+ console.log('Add this entry to your registry\'s `.trust/keys.json`:');
67
+ console.log(JSON.stringify({
68
+ id, alg: 'ed25519',
69
+ publicKey: k.publicKeyB64,
70
+ identityHint: '<your.email@example.com>',
71
+ addedAt: new Date().toISOString(),
72
+ retiredAt: null,
73
+ }, null, 2));
74
+ }
75
+ }
76
+
77
+ /**
78
+ * `wyvrnpm key show-pub --in <priv-file>`
79
+ *
80
+ * Re-derives the public key from a private key file. Handy for verifying
81
+ * that a CI-supplied key matches the keyId pinned in `keys.json` before
82
+ * publishing — derives + prints, without ever writing back to disk.
83
+ */
84
+ async function showPub(argv) {
85
+ const inPath = argv.in;
86
+ if (!inPath) { log.error('--in <priv-file> is required'); process.exit(1); }
87
+ if (!fs.existsSync(inPath)) {
88
+ log.error(`private key file not found: ${inPath}`);
89
+ process.exit(1);
90
+ }
91
+ let derived;
92
+ try {
93
+ derived = ed25519.derivePublicKey(fs.readFileSync(inPath, 'utf8'));
94
+ } catch (err) {
95
+ log.error(err.message);
96
+ process.exit(1);
97
+ }
98
+ if (argv.format === 'json') {
99
+ process.stdout.write(JSON.stringify({
100
+ command: 'key show-pub',
101
+ wyvrnpmVersion: require('../../package.json').version,
102
+ in: inPath,
103
+ publicKeyPem: derived.publicKeyPem,
104
+ publicKey: derived.publicKeyB64,
105
+ }, null, 2) + '\n');
106
+ } else {
107
+ process.stdout.write(derived.publicKeyPem);
108
+ process.stdout.write(`\nbase64: ${derived.publicKeyB64}\n`);
109
+ }
110
+ }
111
+
112
+ module.exports = { gen, showPub };