@pqc-sdk/cli 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/index.js +285 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PQC SDK contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @pqc-sdk/cli
|
|
2
|
+
|
|
3
|
+
[](https://github.com/jeloercc/pqc-sdk/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@pqc-sdk/cli)
|
|
5
|
+
|
|
6
|
+
CLI de [@pqc-sdk/core](https://www.npmjs.com/package/@pqc-sdk/core): proyectos
|
|
7
|
+
post-cuánticos en un comando.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Inicializar proyecto: config + keys de desarrollo + ejemplo funcional
|
|
11
|
+
npx @pqc-sdk/cli init
|
|
12
|
+
|
|
13
|
+
# Generar keys serializadas en base64url
|
|
14
|
+
npx @pqc-sdk/cli keygen --algorithm ml-dsa-65 --out keys/
|
|
15
|
+
|
|
16
|
+
# Detectar crypto pre-cuántico (RSA/ECDSA/ECDH) y qué migrar a PQC
|
|
17
|
+
npx @pqc-sdk/cli audit
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`audit` sale con código 1 si encuentra crypto a migrar — usable como gate de CI.
|
|
21
|
+
El output usa colores solo cuando hay TTY: legible en logs y pipes.
|
|
22
|
+
|
|
23
|
+
## Licencia
|
|
24
|
+
|
|
25
|
+
[MIT](./LICENSE)
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { defineCommand as defineCommand4, runMain } from "citty";
|
|
5
|
+
|
|
6
|
+
// src/commands/audit.ts
|
|
7
|
+
import { readFile, readdir } from "fs/promises";
|
|
8
|
+
import { existsSync } from "fs";
|
|
9
|
+
import { join, relative } from "path";
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
|
+
import pc2 from "picocolors";
|
|
12
|
+
|
|
13
|
+
// src/ui.ts
|
|
14
|
+
import pc from "picocolors";
|
|
15
|
+
var ok = (message) => {
|
|
16
|
+
console.log(`${pc.green("\u2713")} ${message}`);
|
|
17
|
+
};
|
|
18
|
+
var warn = (message) => {
|
|
19
|
+
console.log(`${pc.yellow("\u26A0")} ${pc.yellow(message)}`);
|
|
20
|
+
};
|
|
21
|
+
var item = (message) => {
|
|
22
|
+
console.log(` ${message}`);
|
|
23
|
+
};
|
|
24
|
+
var finding = (location, what, migrateTo) => {
|
|
25
|
+
console.log(` ${pc.red("\u25CF")} ${pc.bold(location)} \u2014 ${what}`);
|
|
26
|
+
console.log(` ${pc.dim("migrar a:")} ${pc.cyan(migrateTo)}`);
|
|
27
|
+
};
|
|
28
|
+
var heading = (message) => {
|
|
29
|
+
console.log(pc.bold(message));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// src/commands/audit.ts
|
|
33
|
+
var ML_DSA = "ML-DSA-65 (pqc.sign / pqc.verify)";
|
|
34
|
+
var ML_KEM = "ML-KEM-768 + AES-256-GCM (pqc.encrypt / pqc.decrypt)";
|
|
35
|
+
var RISKY_PACKAGES = {
|
|
36
|
+
jsonwebtoken: { what: "JWTs firmados con RSA/ECDSA (RS256/ES256)", migrateTo: ML_DSA },
|
|
37
|
+
jose: { what: "JOSE/JWT con algoritmos RSA/ECDSA", migrateTo: ML_DSA },
|
|
38
|
+
elliptic: { what: "Curvas el\xEDpticas cl\xE1sicas (ECDSA/ECDH)", migrateTo: `${ML_DSA} y ${ML_KEM}` },
|
|
39
|
+
secp256k1: { what: "Firmas ECDSA sobre secp256k1", migrateTo: ML_DSA },
|
|
40
|
+
"node-rsa": { what: "Cifrado y firmas RSA", migrateTo: `${ML_KEM} y ${ML_DSA}` },
|
|
41
|
+
"node-forge": { what: "RSA/X.509 cl\xE1sico", migrateTo: `${ML_KEM} y ${ML_DSA}` },
|
|
42
|
+
tweetnacl: { what: "Ed25519/X25519 (pre-cu\xE1ntico)", migrateTo: `${ML_DSA} y ${ML_KEM}` }
|
|
43
|
+
};
|
|
44
|
+
var CODE_PATTERNS = [
|
|
45
|
+
{
|
|
46
|
+
re: /create(?:Sign|Verify)\s*\(/,
|
|
47
|
+
what: "firma RSA/ECDSA v\xEDa node:crypto (createSign/createVerify)",
|
|
48
|
+
migrateTo: ML_DSA
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
re: /createECDH\s*\(|\.diffieHellman\s*\(/,
|
|
52
|
+
what: "intercambio de claves ECDH/DH",
|
|
53
|
+
migrateTo: ML_KEM
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
re: /publicEncrypt\s*\(|privateDecrypt\s*\(/,
|
|
57
|
+
what: "cifrado RSA (publicEncrypt/privateDecrypt)",
|
|
58
|
+
migrateTo: ML_KEM
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
re: /generateKeyPair(?:Sync)?\s*\(\s*['"](?:rsa|rsa-pss|dsa|ec|ed25519|ed448|x25519|x448)['"]/,
|
|
62
|
+
what: "generaci\xF3n de keypair pre-cu\xE1ntico",
|
|
63
|
+
migrateTo: "pqc.keys.generate (ML-KEM-768 para cifrado, ML-DSA-65 para firmas)"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
re: /['"`](?:RS|ES|PS)(?:256|384|512)['"`]/,
|
|
67
|
+
what: "JWT con algoritmo de firma RSA/ECDSA",
|
|
68
|
+
migrateTo: ML_DSA
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
re: /['"`](?:RSA-OAEP|ECDH|ECDSA)['"`]/,
|
|
72
|
+
what: "WebCrypto con algoritmo pre-cu\xE1ntico",
|
|
73
|
+
migrateTo: `${ML_KEM} o ${ML_DSA}`
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs", ".ts", ".mts", ".cts", ".jsx", ".tsx"]);
|
|
77
|
+
var IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "coverage", ".git", ".next"]);
|
|
78
|
+
async function collectSourceFiles(root) {
|
|
79
|
+
const files = [];
|
|
80
|
+
const pending = [root];
|
|
81
|
+
while (pending.length > 0) {
|
|
82
|
+
const dir = pending.pop();
|
|
83
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
84
|
+
if (entry.isDirectory()) {
|
|
85
|
+
if (!IGNORED_DIRS.has(entry.name)) pending.push(join(dir, entry.name));
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const dot = entry.name.lastIndexOf(".");
|
|
89
|
+
if (dot !== -1 && SOURCE_EXTENSIONS.has(entry.name.slice(dot))) {
|
|
90
|
+
files.push(join(dir, entry.name));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return files.sort();
|
|
95
|
+
}
|
|
96
|
+
async function auditPackageJson(cwd) {
|
|
97
|
+
const path = join(cwd, "package.json");
|
|
98
|
+
if (!existsSync(path)) return [];
|
|
99
|
+
const manifest = JSON.parse(await readFile(path, "utf8"));
|
|
100
|
+
const declared = {
|
|
101
|
+
...manifest.dependencies,
|
|
102
|
+
...manifest.devDependencies,
|
|
103
|
+
...manifest.peerDependencies
|
|
104
|
+
};
|
|
105
|
+
return Object.keys(declared).filter((name) => name in RISKY_PACKAGES).map((name) => ({ location: `package.json (${name})`, ...RISKY_PACKAGES[name] }));
|
|
106
|
+
}
|
|
107
|
+
async function auditSources(cwd) {
|
|
108
|
+
const findings = [];
|
|
109
|
+
for (const file of await collectSourceFiles(cwd)) {
|
|
110
|
+
const lines = (await readFile(file, "utf8")).split("\n");
|
|
111
|
+
lines.forEach((line, index) => {
|
|
112
|
+
for (const { re, what, migrateTo } of CODE_PATTERNS) {
|
|
113
|
+
if (re.test(line)) {
|
|
114
|
+
findings.push({ location: `${relative(cwd, file)}:${index + 1}`, what, migrateTo });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return findings;
|
|
120
|
+
}
|
|
121
|
+
var audit = defineCommand({
|
|
122
|
+
meta: {
|
|
123
|
+
name: "audit",
|
|
124
|
+
description: "Detecta crypto pre-cu\xE1ntico y sugiere el equivalente PQC"
|
|
125
|
+
},
|
|
126
|
+
async run() {
|
|
127
|
+
const cwd = process.cwd();
|
|
128
|
+
const findings = [...await auditPackageJson(cwd), ...await auditSources(cwd)];
|
|
129
|
+
if (findings.length === 0) {
|
|
130
|
+
ok("Sin crypto pre-cu\xE1ntico detectado.");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
heading(`Crypto pre-cu\xE1ntico detectado (${findings.length} hallazgos):`);
|
|
134
|
+
for (const f of findings) {
|
|
135
|
+
finding(f.location, f.what, f.migrateTo);
|
|
136
|
+
}
|
|
137
|
+
console.log();
|
|
138
|
+
console.log(
|
|
139
|
+
pc2.yellow(
|
|
140
|
+
`${findings.length} usos a migrar. Gu\xEDa de algoritmos: FIPS 203 (ML-KEM) cifrado, FIPS 204 (ML-DSA) firmas.`
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
process.exitCode = 1;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// src/commands/init.ts
|
|
148
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
149
|
+
import { existsSync as existsSync3 } from "fs";
|
|
150
|
+
import { defineCommand as defineCommand2 } from "citty";
|
|
151
|
+
|
|
152
|
+
// src/keyfiles.ts
|
|
153
|
+
import { chmod, mkdir, writeFile } from "fs/promises";
|
|
154
|
+
import { existsSync as existsSync2 } from "fs";
|
|
155
|
+
import { join as join2 } from "path";
|
|
156
|
+
import { SUPPORTED_ALGORITHMS, pqc } from "@pqc-sdk/core";
|
|
157
|
+
function assertSupportedAlgorithm(value) {
|
|
158
|
+
if (!SUPPORTED_ALGORITHMS.includes(value)) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Algoritmo no soportado: ${value} (soportados: ${SUPPORTED_ALGORITHMS.join(", ")})`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
async function writeKeyPair(directory, baseName, algorithm, force) {
|
|
166
|
+
const publicPath = join2(directory, `${baseName}.public.pqc`);
|
|
167
|
+
const secretPath = join2(directory, `${baseName}.secret.pqc`);
|
|
168
|
+
if (!force) {
|
|
169
|
+
for (const path of [publicPath, secretPath]) {
|
|
170
|
+
if (existsSync2(path)) {
|
|
171
|
+
throw new Error(`${path} ya existe. Us\xE1 --force para sobreescribirla.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const pair = await pqc.keys.generate({ algorithm });
|
|
176
|
+
await mkdir(directory, { recursive: true });
|
|
177
|
+
await writeFile(publicPath, `${pqc.keys.serialize(pair.publicKey)}
|
|
178
|
+
`);
|
|
179
|
+
await writeFile(secretPath, `${pqc.keys.serialize(pair.secretKey)}
|
|
180
|
+
`, { mode: 384 });
|
|
181
|
+
await chmod(secretPath, 384);
|
|
182
|
+
return { algorithm, publicPath, secretPath };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/commands/init.ts
|
|
186
|
+
var CONFIG_FILE = "pqc.config.json";
|
|
187
|
+
var CONFIG = {
|
|
188
|
+
defaultAlgorithm: "ml-kem-768",
|
|
189
|
+
keysDir: "keys"
|
|
190
|
+
};
|
|
191
|
+
var EXAMPLE = `import { pqc } from '@pqc-sdk/core';
|
|
192
|
+
|
|
193
|
+
// Roundtrip completo: generar keys, cifrar y descifrar.
|
|
194
|
+
const pair = await pqc.keys.generate(); // ML-KEM-768 por defecto
|
|
195
|
+
const ciphertext = await pqc.encrypt('hola post-quantum', pair.publicKey);
|
|
196
|
+
const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);
|
|
197
|
+
console.log(new TextDecoder().decode(plaintext)); // "hola post-quantum"
|
|
198
|
+
|
|
199
|
+
// Firmas digitales (ML-DSA-65):
|
|
200
|
+
const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
|
|
201
|
+
const signature = await pqc.sign('documento', signer.secretKey);
|
|
202
|
+
console.log(await pqc.verify('documento', signature, signer.publicKey)); // true
|
|
203
|
+
|
|
204
|
+
// Las keys se serializan a base64url con metadata, listas para persistir:
|
|
205
|
+
const token = pqc.keys.serialize(pair.publicKey);
|
|
206
|
+
console.log(token.slice(0, 48) + '\u2026');
|
|
207
|
+
|
|
208
|
+
// Para cargar las keys de desarrollo que gener\xF3 \`pqc init\`:
|
|
209
|
+
// import { readFile } from 'node:fs/promises';
|
|
210
|
+
// const publicKey = pqc.keys.deserialize(
|
|
211
|
+
// (await readFile('keys/dev.public.pqc', 'utf8')).trim(),
|
|
212
|
+
// );
|
|
213
|
+
`;
|
|
214
|
+
var init = defineCommand2({
|
|
215
|
+
meta: {
|
|
216
|
+
name: "init",
|
|
217
|
+
description: "Inicializa un proyecto: config, keys de desarrollo y ejemplo"
|
|
218
|
+
},
|
|
219
|
+
async run() {
|
|
220
|
+
if (existsSync3(CONFIG_FILE)) {
|
|
221
|
+
throw new Error(`${CONFIG_FILE} ya existe: el proyecto ya est\xE1 inicializado.`);
|
|
222
|
+
}
|
|
223
|
+
await writeFile2(CONFIG_FILE, `${JSON.stringify(CONFIG, null, 2)}
|
|
224
|
+
`);
|
|
225
|
+
const keys = await writeKeyPair(CONFIG.keysDir, "dev", CONFIG.defaultAlgorithm, false);
|
|
226
|
+
await writeFile2("example.ts", EXAMPLE);
|
|
227
|
+
heading("Proyecto PQC inicializado:");
|
|
228
|
+
item(`${CONFIG_FILE} \u2014 configuraci\xF3n con defaults seguros`);
|
|
229
|
+
item(`${keys.publicPath} / ${keys.secretPath} \u2014 par ${keys.algorithm} de desarrollo`);
|
|
230
|
+
item("example.ts \u2014 roundtrip completo listo para ejecutar");
|
|
231
|
+
console.log();
|
|
232
|
+
warn("Las keys de keys/dev.* son SOLO de desarrollo \u2014 NO usarlas en producci\xF3n.");
|
|
233
|
+
ok(`Siguiente paso: ejecut\xE1 example.ts (node --experimental-strip-types example.ts o tsx)`);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// src/commands/keygen.ts
|
|
238
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
239
|
+
var keygen = defineCommand3({
|
|
240
|
+
meta: {
|
|
241
|
+
name: "keygen",
|
|
242
|
+
description: "Genera un par de keys PQC serializadas en base64url"
|
|
243
|
+
},
|
|
244
|
+
args: {
|
|
245
|
+
algorithm: {
|
|
246
|
+
type: "string",
|
|
247
|
+
description: "Algoritmo del par (ml-kem-768 o ml-dsa-65)",
|
|
248
|
+
default: "ml-kem-768"
|
|
249
|
+
},
|
|
250
|
+
out: {
|
|
251
|
+
type: "string",
|
|
252
|
+
description: "Directorio de salida",
|
|
253
|
+
default: "keys"
|
|
254
|
+
},
|
|
255
|
+
force: {
|
|
256
|
+
type: "boolean",
|
|
257
|
+
description: "Sobreescribir keys existentes",
|
|
258
|
+
default: false
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
async run({ args }) {
|
|
262
|
+
const algorithm = assertSupportedAlgorithm(args.algorithm);
|
|
263
|
+
const keys = await writeKeyPair(args.out, algorithm, algorithm, args.force);
|
|
264
|
+
ok(`Par ${algorithm} generado:`);
|
|
265
|
+
item(`p\xFAblica: ${keys.publicPath}`);
|
|
266
|
+
item(`secreta: ${keys.secretPath} (modo 0600)`);
|
|
267
|
+
warn("La key secreta no debe commitearse ni salir de este entorno.");
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// src/index.ts
|
|
272
|
+
var main = defineCommand4({
|
|
273
|
+
meta: {
|
|
274
|
+
name: "pqc",
|
|
275
|
+
version: "0.0.1",
|
|
276
|
+
description: "CLI del SDK de criptograf\xEDa post-cu\xE1ntica (@pqc-sdk/core)"
|
|
277
|
+
},
|
|
278
|
+
subCommands: {
|
|
279
|
+
init,
|
|
280
|
+
keygen,
|
|
281
|
+
audit
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
await runMain(main);
|
|
285
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/audit.ts","../src/ui.ts","../src/commands/init.ts","../src/keyfiles.ts","../src/commands/keygen.ts"],"sourcesContent":["import { defineCommand, runMain } from 'citty';\n\nimport { audit } from './commands/audit.js';\nimport { init } from './commands/init.js';\nimport { keygen } from './commands/keygen.js';\n\nconst main = defineCommand({\n meta: {\n name: 'pqc',\n version: '0.0.1',\n description: 'CLI del SDK de criptografía post-cuántica (@pqc-sdk/core)',\n },\n subCommands: {\n init,\n keygen,\n audit,\n },\n});\n\nawait runMain(main);\n","import { readFile, readdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\nimport { defineCommand } from 'citty';\nimport pc from 'picocolors';\n\nimport { finding, heading, ok } from '../ui.js';\n\ninterface Finding {\n location: string;\n what: string;\n migrateTo: string;\n}\n\nconst ML_DSA = 'ML-DSA-65 (pqc.sign / pqc.verify)';\nconst ML_KEM = 'ML-KEM-768 + AES-256-GCM (pqc.encrypt / pqc.decrypt)';\n\nconst RISKY_PACKAGES: Record<string, { what: string; migrateTo: string }> = {\n jsonwebtoken: { what: 'JWTs firmados con RSA/ECDSA (RS256/ES256)', migrateTo: ML_DSA },\n jose: { what: 'JOSE/JWT con algoritmos RSA/ECDSA', migrateTo: ML_DSA },\n elliptic: { what: 'Curvas elípticas clásicas (ECDSA/ECDH)', migrateTo: `${ML_DSA} y ${ML_KEM}` },\n secp256k1: { what: 'Firmas ECDSA sobre secp256k1', migrateTo: ML_DSA },\n 'node-rsa': { what: 'Cifrado y firmas RSA', migrateTo: `${ML_KEM} y ${ML_DSA}` },\n 'node-forge': { what: 'RSA/X.509 clásico', migrateTo: `${ML_KEM} y ${ML_DSA}` },\n tweetnacl: { what: 'Ed25519/X25519 (pre-cuántico)', migrateTo: `${ML_DSA} y ${ML_KEM}` },\n};\n\nconst CODE_PATTERNS: ReadonlyArray<{ re: RegExp; what: string; migrateTo: string }> = [\n {\n re: /create(?:Sign|Verify)\\s*\\(/,\n what: 'firma RSA/ECDSA vía node:crypto (createSign/createVerify)',\n migrateTo: ML_DSA,\n },\n {\n re: /createECDH\\s*\\(|\\.diffieHellman\\s*\\(/,\n what: 'intercambio de claves ECDH/DH',\n migrateTo: ML_KEM,\n },\n {\n re: /publicEncrypt\\s*\\(|privateDecrypt\\s*\\(/,\n what: 'cifrado RSA (publicEncrypt/privateDecrypt)',\n migrateTo: ML_KEM,\n },\n {\n re: /generateKeyPair(?:Sync)?\\s*\\(\\s*['\"](?:rsa|rsa-pss|dsa|ec|ed25519|ed448|x25519|x448)['\"]/,\n what: 'generación de keypair pre-cuántico',\n migrateTo: 'pqc.keys.generate (ML-KEM-768 para cifrado, ML-DSA-65 para firmas)',\n },\n {\n re: /['\"`](?:RS|ES|PS)(?:256|384|512)['\"`]/,\n what: 'JWT con algoritmo de firma RSA/ECDSA',\n migrateTo: ML_DSA,\n },\n {\n re: /['\"`](?:RSA-OAEP|ECDH|ECDSA)['\"`]/,\n what: 'WebCrypto con algoritmo pre-cuántico',\n migrateTo: `${ML_KEM} o ${ML_DSA}`,\n },\n];\n\nconst SOURCE_EXTENSIONS = new Set(['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts', '.jsx', '.tsx']);\nconst IGNORED_DIRS = new Set(['node_modules', 'dist', 'build', 'coverage', '.git', '.next']);\n\nasync function collectSourceFiles(root: string): Promise<string[]> {\n const files: string[] = [];\n const pending = [root];\n while (pending.length > 0) {\n const dir = pending.pop()!;\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (!IGNORED_DIRS.has(entry.name)) pending.push(join(dir, entry.name));\n continue;\n }\n const dot = entry.name.lastIndexOf('.');\n if (dot !== -1 && SOURCE_EXTENSIONS.has(entry.name.slice(dot))) {\n files.push(join(dir, entry.name));\n }\n }\n }\n return files.sort();\n}\n\nasync function auditPackageJson(cwd: string): Promise<Finding[]> {\n const path = join(cwd, 'package.json');\n if (!existsSync(path)) return [];\n const manifest = JSON.parse(await readFile(path, 'utf8')) as Record<\n string,\n Record<string, string> | undefined\n >;\n const declared = {\n ...manifest.dependencies,\n ...manifest.devDependencies,\n ...manifest.peerDependencies,\n };\n return Object.keys(declared)\n .filter((name) => name in RISKY_PACKAGES)\n .map((name) => ({ location: `package.json (${name})`, ...RISKY_PACKAGES[name]! }));\n}\n\nasync function auditSources(cwd: string): Promise<Finding[]> {\n const findings: Finding[] = [];\n for (const file of await collectSourceFiles(cwd)) {\n const lines = (await readFile(file, 'utf8')).split('\\n');\n lines.forEach((line, index) => {\n for (const { re, what, migrateTo } of CODE_PATTERNS) {\n if (re.test(line)) {\n findings.push({ location: `${relative(cwd, file)}:${index + 1}`, what, migrateTo });\n }\n }\n });\n }\n return findings;\n}\n\nexport const audit = defineCommand({\n meta: {\n name: 'audit',\n description: 'Detecta crypto pre-cuántico y sugiere el equivalente PQC',\n },\n async run() {\n const cwd = process.cwd();\n const findings = [...(await auditPackageJson(cwd)), ...(await auditSources(cwd))];\n\n if (findings.length === 0) {\n ok('Sin crypto pre-cuántico detectado.');\n return;\n }\n\n heading(`Crypto pre-cuántico detectado (${findings.length} hallazgos):`);\n for (const f of findings) {\n finding(f.location, f.what, f.migrateTo);\n }\n console.log();\n console.log(\n pc.yellow(\n `${findings.length} usos a migrar. Guía de algoritmos: FIPS 203 (ML-KEM) cifrado, FIPS 204 (ML-DSA) firmas.`,\n ),\n );\n process.exitCode = 1;\n },\n});\n","import pc from 'picocolors';\n\n/**\n * Helpers de salida. picocolors desactiva los colores automáticamente cuando\n * no hay TTY (y NO_COLOR/FORCE_COLOR se respetan), así el output queda legible\n * en pipes y logs de CI sin códigos ANSI.\n */\nexport const ok = (message: string): void => {\n console.log(`${pc.green('✓')} ${message}`);\n};\n\nexport const warn = (message: string): void => {\n console.log(`${pc.yellow('⚠')} ${pc.yellow(message)}`);\n};\n\nexport const item = (message: string): void => {\n console.log(` ${message}`);\n};\n\nexport const finding = (location: string, what: string, migrateTo: string): void => {\n console.log(` ${pc.red('●')} ${pc.bold(location)} — ${what}`);\n console.log(` ${pc.dim('migrar a:')} ${pc.cyan(migrateTo)}`);\n};\n\nexport const heading = (message: string): void => {\n console.log(pc.bold(message));\n};\n","import { writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\n\nimport { defineCommand } from 'citty';\n\nimport { writeKeyPair } from '../keyfiles.js';\nimport { heading, item, ok, warn } from '../ui.js';\n\nconst CONFIG_FILE = 'pqc.config.json';\n\nconst CONFIG = {\n defaultAlgorithm: 'ml-kem-768',\n keysDir: 'keys',\n} as const;\n\nconst EXAMPLE = `import { pqc } from '@pqc-sdk/core';\n\n// Roundtrip completo: generar keys, cifrar y descifrar.\nconst pair = await pqc.keys.generate(); // ML-KEM-768 por defecto\nconst ciphertext = await pqc.encrypt('hola post-quantum', pair.publicKey);\nconst plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\nconsole.log(new TextDecoder().decode(plaintext)); // \"hola post-quantum\"\n\n// Firmas digitales (ML-DSA-65):\nconst signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\nconst signature = await pqc.sign('documento', signer.secretKey);\nconsole.log(await pqc.verify('documento', signature, signer.publicKey)); // true\n\n// Las keys se serializan a base64url con metadata, listas para persistir:\nconst token = pqc.keys.serialize(pair.publicKey);\nconsole.log(token.slice(0, 48) + '…');\n\n// Para cargar las keys de desarrollo que generó \\`pqc init\\`:\n// import { readFile } from 'node:fs/promises';\n// const publicKey = pqc.keys.deserialize(\n// (await readFile('keys/dev.public.pqc', 'utf8')).trim(),\n// );\n`;\n\nexport const init = defineCommand({\n meta: {\n name: 'init',\n description: 'Inicializa un proyecto: config, keys de desarrollo y ejemplo',\n },\n async run() {\n if (existsSync(CONFIG_FILE)) {\n throw new Error(`${CONFIG_FILE} ya existe: el proyecto ya está inicializado.`);\n }\n\n await writeFile(CONFIG_FILE, `${JSON.stringify(CONFIG, null, 2)}\\n`);\n const keys = await writeKeyPair(CONFIG.keysDir, 'dev', CONFIG.defaultAlgorithm, false);\n await writeFile('example.ts', EXAMPLE);\n\n heading('Proyecto PQC inicializado:');\n item(`${CONFIG_FILE} — configuración con defaults seguros`);\n item(`${keys.publicPath} / ${keys.secretPath} — par ${keys.algorithm} de desarrollo`);\n item('example.ts — roundtrip completo listo para ejecutar');\n console.log();\n warn('Las keys de keys/dev.* son SOLO de desarrollo — NO usarlas en producción.');\n ok(`Siguiente paso: ejecutá example.ts (node --experimental-strip-types example.ts o tsx)`);\n },\n});\n","import { chmod, mkdir, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { SUPPORTED_ALGORITHMS, pqc, type SupportedAlgorithm } from '@pqc-sdk/core';\n\nexport interface WrittenKeyPair {\n algorithm: SupportedAlgorithm;\n publicPath: string;\n secretPath: string;\n}\n\nexport function assertSupportedAlgorithm(value: string): SupportedAlgorithm {\n if (!(SUPPORTED_ALGORITHMS as readonly string[]).includes(value)) {\n throw new Error(\n `Algoritmo no soportado: ${value} (soportados: ${SUPPORTED_ALGORITHMS.join(', ')})`,\n );\n }\n return value as SupportedAlgorithm;\n}\n\n/** Genera un par y lo escribe serializado en base64url, un archivo por key. */\nexport async function writeKeyPair(\n directory: string,\n baseName: string,\n algorithm: SupportedAlgorithm,\n force: boolean,\n): Promise<WrittenKeyPair> {\n const publicPath = join(directory, `${baseName}.public.pqc`);\n const secretPath = join(directory, `${baseName}.secret.pqc`);\n\n if (!force) {\n for (const path of [publicPath, secretPath]) {\n if (existsSync(path)) {\n throw new Error(`${path} ya existe. Usá --force para sobreescribirla.`);\n }\n }\n }\n\n const pair = await pqc.keys.generate({ algorithm });\n await mkdir(directory, { recursive: true });\n await writeFile(publicPath, `${pqc.keys.serialize(pair.publicKey)}\\n`);\n await writeFile(secretPath, `${pqc.keys.serialize(pair.secretKey)}\\n`, { mode: 0o600 });\n await chmod(secretPath, 0o600);\n\n return { algorithm, publicPath, secretPath };\n}\n","import { defineCommand } from 'citty';\n\nimport { assertSupportedAlgorithm, writeKeyPair } from '../keyfiles.js';\nimport { item, ok, warn } from '../ui.js';\n\nexport const keygen = defineCommand({\n meta: {\n name: 'keygen',\n description: 'Genera un par de keys PQC serializadas en base64url',\n },\n args: {\n algorithm: {\n type: 'string',\n description: 'Algoritmo del par (ml-kem-768 o ml-dsa-65)',\n default: 'ml-kem-768',\n },\n out: {\n type: 'string',\n description: 'Directorio de salida',\n default: 'keys',\n },\n force: {\n type: 'boolean',\n description: 'Sobreescribir keys existentes',\n default: false,\n },\n },\n async run({ args }) {\n const algorithm = assertSupportedAlgorithm(args.algorithm);\n const keys = await writeKeyPair(args.out, algorithm, algorithm, args.force);\n\n ok(`Par ${algorithm} generado:`);\n item(`pública: ${keys.publicPath}`);\n item(`secreta: ${keys.secretPath} (modo 0600)`);\n warn('La key secreta no debe commitearse ni salir de este entorno.');\n },\n});\n"],"mappings":"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","names":["defineCommand","pc","pc","writeFile","existsSync","defineCommand","existsSync","join","defineCommand","existsSync","writeFile","defineCommand","defineCommand","defineCommand"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pqc-sdk/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI del SDK de criptografía post-cuántica",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"pqc": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"citty": "^0.2.2",
|
|
17
|
+
"picocolors": "^1.1.1",
|
|
18
|
+
"@pqc-sdk/core": "0.1.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^22.15.29",
|
|
22
|
+
"tsup": "^8.5.0",
|
|
23
|
+
"vitest": "^3.2.6"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"homepage": "https://github.com/jeloercc/pqc-sdk#readme",
|
|
27
|
+
"bugs": "https://github.com/jeloercc/pqc-sdk/issues",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"post-quantum",
|
|
33
|
+
"pqc",
|
|
34
|
+
"cli",
|
|
35
|
+
"ml-kem",
|
|
36
|
+
"ml-dsa",
|
|
37
|
+
"audit"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/jeloercc/pqc-sdk.git",
|
|
42
|
+
"directory": "packages/cli"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"dev": "tsup --watch",
|
|
47
|
+
"lint": "eslint . && tsc --noEmit",
|
|
48
|
+
"test": "pnpm run build && vitest run"
|
|
49
|
+
}
|
|
50
|
+
}
|