postquant 0.0.1 → 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PostQuant 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,109 @@
1
+ # PostQuant
2
+
3
+ **Find quantum-vulnerable cryptography in your TLS endpoints.**
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![npm version](https://img.shields.io/npm/v/postquant)](https://www.npmjs.com/package/postquant)
7
+
8
+ PostQuant scans TLS connections and reports which algorithms are vulnerable to quantum attacks. It grades endpoints A+ through F and tells you what to migrate to.
9
+
10
+ > **Early development.** The TLS scanner works. Code scanning and CBOM generation are planned.
11
+
12
+ ## Why
13
+
14
+ NIST will **deprecate** RSA, ECC, and other quantum-vulnerable algorithms by **2030** and **disallow** them by **2035**. Adversaries are already harvesting encrypted traffic to decrypt later with quantum computers.
15
+
16
+ PostQuant shows you what's exposed.
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ npx postquant scan example.com
22
+ ```
23
+
24
+ Output:
25
+
26
+ ```
27
+ Overall Grade: C
28
+
29
+ Certificate
30
+ Algorithm: ECDSA P-256 🔴 Quantum Vulnerable
31
+
32
+ Connection
33
+ Protocol: TLS 1.3 🟢 Current
34
+ Key Exchange: X25519 🔴 Quantum Vulnerable
35
+ Cipher: AES-256-GCM 🟢 Quantum Safe
36
+ ```
37
+
38
+ Most sites today score C or D. That's expected — almost nobody has deployed post-quantum cryptography yet.
39
+
40
+ ## Usage
41
+
42
+ ```bash
43
+ # Scan a single host
44
+ postquant scan example.com
45
+
46
+ # Scan with explicit port
47
+ postquant scan example.com:8443
48
+
49
+ # Scan multiple hosts
50
+ postquant scan example.com api.example.com
51
+
52
+ # JSON output
53
+ postquant scan example.com --format json
54
+
55
+ # Read hosts from a file (one per line)
56
+ postquant scan --file hosts.txt
57
+
58
+ # Set connection timeout
59
+ postquant scan example.com --timeout 5000
60
+ ```
61
+
62
+ ## Grading
63
+
64
+ | Grade | Meaning |
65
+ |-------|---------|
66
+ | **A+** | All quantum-safe algorithms (PQC key exchange + signatures) |
67
+ | **A** | Quantum-safe with minor observations |
68
+ | **B** | Mostly safe, some moderate-risk items (e.g., AES-128) |
69
+ | **C** | Quantum-vulnerable key exchange or signatures, but TLS 1.3 |
70
+ | **D** | Multiple quantum-vulnerable components |
71
+ | **F** | Critical vulnerabilities + legacy protocols |
72
+
73
+ ## Development
74
+
75
+ ```bash
76
+ npm install # Install dependencies
77
+ npm run build # Compile TypeScript
78
+ npm test # Run tests
79
+ npm run dev -- scan example.com # Run from source
80
+ ```
81
+
82
+ ## Roadmap
83
+
84
+ | Phase | Target | Status |
85
+ |-------|--------|--------|
86
+ | TLS scanner CLI | March 2026 | v0.1.0 |
87
+ | Code scanner (Python, JS, Go, Java) | April 2026 | Planned |
88
+ | CBOM generation + risk scoring | May 2026 | Planned |
89
+ | Web dashboard | June 2026 | Planned |
90
+
91
+ See [docs/ROADMAP.md](docs/ROADMAP.md) for details.
92
+
93
+ ## Contributing
94
+
95
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
96
+
97
+ ## Security
98
+
99
+ See [SECURITY.md](SECURITY.md).
100
+
101
+ ## License
102
+
103
+ [MIT](LICENSE)
104
+
105
+ ## Links
106
+
107
+ - [postquant.dev](https://postquant.dev)
108
+ - [@postquantdev](https://x.com/postquantdev)
109
+ - [npm](https://www.npmjs.com/package/postquant)
@@ -0,0 +1,3 @@
1
+ import type { ScanOptions } from '../types/index.js';
2
+ export declare function scanCommand(hosts: string[], options: ScanOptions): Promise<number>;
3
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAgB,WAAW,EAAS,MAAM,mBAAmB,CAAC;AA+B1E,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAwDjB"}
@@ -0,0 +1,88 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import chalk from 'chalk';
3
+ import { scanHost } from '../scanner/tls.js';
4
+ import { classify } from '../scanner/classifier.js';
5
+ import { grade, shouldFailForGrade } from '../scanner/grader.js';
6
+ import { formatTerminal } from '../output/terminal.js';
7
+ import { formatJson } from '../output/json.js';
8
+ function parseHost(input) {
9
+ const lastColon = input.lastIndexOf(':');
10
+ if (lastColon === -1) {
11
+ return { host: input, port: 443 };
12
+ }
13
+ const portStr = input.slice(lastColon + 1);
14
+ const port = parseInt(portStr, 10);
15
+ if (isNaN(port) || port <= 0 || port > 65535) {
16
+ return { host: input, port: 443 };
17
+ }
18
+ return { host: input.slice(0, lastColon), port };
19
+ }
20
+ function readHostsFile(filePath) {
21
+ const content = readFileSync(filePath, 'utf-8');
22
+ return content
23
+ .split('\n')
24
+ .map((line) => line.trim())
25
+ .filter((line) => line.length > 0 && !line.startsWith('#'));
26
+ }
27
+ export async function scanCommand(hosts, options) {
28
+ const allHostInputs = [...hosts];
29
+ if (options.file) {
30
+ try {
31
+ const fileHosts = readHostsFile(options.file);
32
+ allHostInputs.push(...fileHosts);
33
+ }
34
+ catch (err) {
35
+ console.error(chalk.red(`Error reading hosts file: ${err.message}`));
36
+ return 1;
37
+ }
38
+ }
39
+ if (allHostInputs.length === 0) {
40
+ console.error(chalk.red('No hosts specified. Use: postquant scan <host> or --file <path>'));
41
+ return 1;
42
+ }
43
+ const results = [];
44
+ let hadErrors = false;
45
+ for (const input of allHostInputs) {
46
+ const { host, port } = parseHost(input);
47
+ try {
48
+ const scanResult = await scanHost(host, port, options.timeout);
49
+ const classified = classify(scanResult);
50
+ const graded = grade(classified);
51
+ results.push(graded);
52
+ }
53
+ catch (err) {
54
+ hadErrors = true;
55
+ console.error(chalk.red(`\nError scanning ${host}:${port}: ${err.message}`));
56
+ }
57
+ }
58
+ if (results.length > 0) {
59
+ if (options.format === 'json') {
60
+ console.log(formatJson(results));
61
+ }
62
+ else {
63
+ for (const result of results) {
64
+ console.log(formatTerminal(result));
65
+ }
66
+ }
67
+ }
68
+ if (hadErrors)
69
+ return 1;
70
+ const worstGrade = getWorstGrade(results);
71
+ if (worstGrade && shouldFailForGrade(worstGrade, options.failGrade)) {
72
+ return 1;
73
+ }
74
+ return 0;
75
+ }
76
+ const GRADE_ORDER = ['A+', 'A', 'B', 'C', 'D', 'F'];
77
+ function getWorstGrade(results) {
78
+ if (results.length === 0)
79
+ return null;
80
+ let worst = 0;
81
+ for (const r of results) {
82
+ const idx = GRADE_ORDER.indexOf(r.grade);
83
+ if (idx > worst)
84
+ worst = idx;
85
+ }
86
+ return GRADE_ORDER[worst];
87
+ }
88
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { scanCommand } from './commands/scan.js';
4
+ const VALID_GRADES = ['A+', 'A', 'B', 'C', 'D', 'F'];
5
+ const program = new Command();
6
+ program
7
+ .name('postquant')
8
+ .description('Scan TLS endpoints for quantum-vulnerable cryptography')
9
+ .version('0.1.0');
10
+ program
11
+ .command('scan')
12
+ .description('Scan one or more TLS endpoints for quantum readiness')
13
+ .argument('[hosts...]', 'Hostnames to scan (with optional :port)')
14
+ .option('-f, --format <format>', 'Output format (terminal, json)', 'terminal')
15
+ .option('--file <path>', 'Read hosts from file (one per line)')
16
+ .option('--timeout <ms>', 'Connection timeout in milliseconds', '10000')
17
+ .option('--verbose', 'Show raw TLS handshake details', false)
18
+ .option('--fail-grade <grade>', 'Exit non-zero at this grade or worse', 'C')
19
+ .action(async (hosts, opts) => {
20
+ const format = opts.format;
21
+ if (format !== 'terminal' && format !== 'json') {
22
+ console.error(`Invalid format: ${format}. Use 'terminal' or 'json'.`);
23
+ process.exit(1);
24
+ }
25
+ const failGrade = opts.failGrade;
26
+ if (!VALID_GRADES.includes(failGrade)) {
27
+ console.error(`Invalid fail-grade: ${failGrade}. Use one of: ${VALID_GRADES.join(', ')}`);
28
+ process.exit(1);
29
+ }
30
+ const exitCode = await scanCommand(hosts, {
31
+ format,
32
+ timeout: parseInt(opts.timeout, 10),
33
+ verbose: opts.verbose,
34
+ failGrade,
35
+ file: opts.file,
36
+ });
37
+ process.exit(exitCode);
38
+ });
39
+ program.parse();
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,YAAY,GAAY,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAE9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,QAAQ,CAAC,YAAY,EAAE,yCAAyC,CAAC;KACjE,MAAM,CAAC,uBAAuB,EAAE,gCAAgC,EAAE,UAAU,CAAC;KAC7E,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC;KAC9D,MAAM,CAAC,gBAAgB,EAAE,oCAAoC,EAAE,OAAO,CAAC;KACvE,MAAM,CAAC,WAAW,EAAE,gCAAgC,EAAE,KAAK,CAAC;KAC5D,MAAM,CACL,sBAAsB,EACtB,sCAAsC,EACtC,GAAG,CACJ;KACA,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,IAAI,EAAE,EAAE;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAsB,CAAC;IAC3C,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,6BAA6B,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAkB,CAAC;IAC1C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CACX,uBAAuB,SAAS,iBAAiB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE;QACxC,MAAM;QACN,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACnC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS;QACT,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC,CAAC;IAEH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GradedResult } from '../types/index.js';
2
+ export declare function formatJson(results: GradedResult[]): string;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AActD,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAc1D"}
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { dirname, join } from 'node:path';
4
+ function getVersion() {
5
+ try {
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
8
+ return pkg.version;
9
+ }
10
+ catch {
11
+ return '0.1.0';
12
+ }
13
+ }
14
+ export function formatJson(results) {
15
+ const output = {
16
+ version: getVersion(),
17
+ timestamp: new Date().toISOString(),
18
+ results: results.map((r) => ({
19
+ target: `${r.host}:${r.port}`,
20
+ grade: r.grade,
21
+ findings: r.findings,
22
+ summary: r.summary,
23
+ migrationNotes: r.migrationNotes,
24
+ })),
25
+ };
26
+ return JSON.stringify(output, null, 2);
27
+ }
28
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CACnE,CAAC;QACF,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAuB;IAChD,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,UAAU,EAAE;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE;YAC7B,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,cAAc,EAAE,CAAC,CAAC,cAAc;SACjC,CAAC,CAAC;KACJ,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GradedResult } from '../types/index.js';
2
+ export declare function formatTerminal(result: GradedResult): string;
3
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/output/terminal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AAwCxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAwG3D"}
@@ -0,0 +1,103 @@
1
+ import chalk from 'chalk';
2
+ const VERSION = '0.1.0';
3
+ function riskIcon(risk) {
4
+ switch (risk) {
5
+ case 'critical':
6
+ return chalk.red('🔴 Quantum Vulnerable');
7
+ case 'moderate':
8
+ return chalk.yellow('🟡 Moderate Risk');
9
+ case 'safe':
10
+ return chalk.green('🟢 Quantum Safe');
11
+ }
12
+ }
13
+ function protocolLabel(risk) {
14
+ switch (risk) {
15
+ case 'critical':
16
+ return chalk.red('🔴 Legacy (Insecure)');
17
+ case 'moderate':
18
+ return chalk.yellow('🟡 Aging');
19
+ case 'safe':
20
+ return chalk.green('🟢 Current');
21
+ }
22
+ }
23
+ function gradeColor(grade) {
24
+ switch (grade) {
25
+ case 'A+':
26
+ case 'A':
27
+ return chalk.green.bold(grade);
28
+ case 'B':
29
+ return chalk.yellow.bold(grade);
30
+ case 'C':
31
+ case 'D':
32
+ case 'F':
33
+ return chalk.red.bold(grade);
34
+ }
35
+ }
36
+ export function formatTerminal(result) {
37
+ const lines = [];
38
+ const bar = '━'.repeat(48);
39
+ lines.push('');
40
+ lines.push(chalk.bold(`🔐 PostQuant v${VERSION} — Quantum Readiness Scanner`));
41
+ lines.push(chalk.dim(bar));
42
+ lines.push('');
43
+ lines.push(` Target: ${chalk.bold(`${result.host}:${result.port}`)}`);
44
+ lines.push('');
45
+ lines.push(` Overall Grade: ${gradeColor(result.grade)}`);
46
+ lines.push('');
47
+ const certFinding = result.findings.find((f) => f.component === 'certificate');
48
+ if (certFinding) {
49
+ lines.push(' Certificate');
50
+ const algoStr = certFinding.curve
51
+ ? `${certFinding.algorithm} ${certFinding.curve}`
52
+ : certFinding.keySize
53
+ ? `${certFinding.algorithm}-${certFinding.keySize}`
54
+ : certFinding.algorithm;
55
+ lines.push(` Algorithm: ${algoStr.padEnd(20)} ${riskIcon(certFinding.risk)}`);
56
+ }
57
+ const protocolFinding = result.findings.find((f) => f.component === 'protocol');
58
+ const kxFinding = result.findings.find((f) => f.component === 'keyExchange');
59
+ const cipherFinding = result.findings.find((f) => f.component === 'cipher');
60
+ const hashFinding = result.findings.find((f) => f.component === 'hash');
61
+ lines.push('');
62
+ lines.push(' Connection');
63
+ if (protocolFinding) {
64
+ lines.push(` Protocol: ${protocolFinding.algorithm.padEnd(20)} ${protocolLabel(protocolFinding.risk)}`);
65
+ }
66
+ if (kxFinding) {
67
+ lines.push(` Key Exchange: ${kxFinding.algorithm.padEnd(20)} ${riskIcon(kxFinding.risk)}`);
68
+ }
69
+ if (cipherFinding) {
70
+ lines.push(` Cipher: ${cipherFinding.algorithm.padEnd(20)} ${riskIcon(cipherFinding.risk)}`);
71
+ }
72
+ if (hashFinding) {
73
+ const hashLabel = cipherFinding?.algorithm.includes('GCM') ||
74
+ cipherFinding?.algorithm.includes('CHACHA')
75
+ ? 'AEAD'
76
+ : hashFinding.algorithm;
77
+ lines.push(` MAC: ${hashLabel.padEnd(20)} ${riskIcon(hashFinding.risk)}`);
78
+ }
79
+ lines.push('');
80
+ lines.push(' Summary');
81
+ if (result.summary.critical > 0) {
82
+ lines.push(chalk.red(` 🔴 ${result.summary.critical} quantum-vulnerable finding${result.summary.critical > 1 ? 's' : ''}`));
83
+ }
84
+ if (result.summary.moderate > 0) {
85
+ lines.push(chalk.yellow(` 🟡 ${result.summary.moderate} moderate-risk finding${result.summary.moderate > 1 ? 's' : ''}`));
86
+ }
87
+ if (result.summary.safe > 0) {
88
+ lines.push(chalk.green(` 🟢 ${result.summary.safe} quantum-safe finding${result.summary.safe > 1 ? 's' : ''}`));
89
+ }
90
+ if (result.migrationNotes.length > 0) {
91
+ lines.push('');
92
+ lines.push(' Migration Notes');
93
+ for (const note of result.migrationNotes) {
94
+ lines.push(` • ${note}`);
95
+ }
96
+ lines.push(chalk.dim(' • NIST Timeline: Current algorithms deprecated 2030, disallowed 2035'));
97
+ }
98
+ lines.push('');
99
+ lines.push(chalk.dim(bar));
100
+ lines.push('');
101
+ return lines.join('\n');
102
+ }
103
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/output/terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TlsScanResult, ClassifiedResult } from '../types/index.js';
2
+ export declare function classify(scan: TlsScanResult): ClassifiedResult;
3
+ //# sourceMappingURL=classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/scanner/classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAEb,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,CAY9D"}
@@ -0,0 +1,283 @@
1
+ export function classify(scan) {
2
+ return {
3
+ host: scan.host,
4
+ port: scan.port,
5
+ findings: [
6
+ classifyProtocol(scan),
7
+ classifyCertificate(scan),
8
+ classifyKeyExchange(scan),
9
+ classifyCipher(scan),
10
+ classifyHash(scan),
11
+ ],
12
+ };
13
+ }
14
+ function classifyProtocol(scan) {
15
+ const protocol = scan.protocol ?? '';
16
+ if (protocol === 'TLSv1.3') {
17
+ return {
18
+ component: 'protocol',
19
+ algorithm: 'TLS 1.3',
20
+ risk: 'safe',
21
+ reason: 'Current protocol version',
22
+ };
23
+ }
24
+ if (protocol === 'TLSv1.2') {
25
+ return {
26
+ component: 'protocol',
27
+ algorithm: 'TLS 1.2',
28
+ risk: 'moderate',
29
+ reason: 'Aging protocol, still functional',
30
+ migration: 'Upgrade to TLS 1.3',
31
+ };
32
+ }
33
+ const version = protocol || 'Unknown';
34
+ return {
35
+ component: 'protocol',
36
+ algorithm: version,
37
+ risk: 'critical',
38
+ reason: 'Legacy protocol, already insecure',
39
+ migration: 'Upgrade to TLS 1.3 immediately',
40
+ };
41
+ }
42
+ function classifyCertificate(scan) {
43
+ if (!scan.certificate) {
44
+ return {
45
+ component: 'certificate',
46
+ algorithm: 'Unknown',
47
+ risk: 'critical',
48
+ reason: 'Unknown algorithm — assumed vulnerable',
49
+ migration: 'ML-DSA (FIPS 204)',
50
+ };
51
+ }
52
+ const algo = scan.certificate.publicKeyAlgorithm.toUpperCase();
53
+ const keySize = scan.certificate.publicKeySize;
54
+ const pqcAlgos = ['ML-DSA', 'ML-KEM', 'SLH-DSA', 'HQC'];
55
+ if (pqcAlgos.some((pqc) => algo.includes(pqc.toUpperCase()))) {
56
+ return {
57
+ component: 'certificate',
58
+ algorithm: scan.certificate.publicKeyAlgorithm,
59
+ keySize,
60
+ risk: 'safe',
61
+ reason: 'NIST post-quantum standard',
62
+ };
63
+ }
64
+ const classicalAlgos = ['RSA', 'EC', 'ECDSA', 'ED25519', 'ED448', 'DSA', 'DH'];
65
+ if (classicalAlgos.some((ca) => algo.includes(ca))) {
66
+ return {
67
+ component: 'certificate',
68
+ algorithm: scan.certificate.publicKeyAlgorithm,
69
+ keySize,
70
+ curve: scan.certificate.curve,
71
+ risk: 'critical',
72
+ reason: "Vulnerable to Shor's algorithm",
73
+ migration: 'ML-DSA (FIPS 204)',
74
+ };
75
+ }
76
+ return {
77
+ component: 'certificate',
78
+ algorithm: scan.certificate.publicKeyAlgorithm,
79
+ keySize,
80
+ risk: 'critical',
81
+ reason: 'Unknown algorithm — assumed vulnerable',
82
+ migration: 'ML-DSA (FIPS 204)',
83
+ };
84
+ }
85
+ function isPqcKeyExchange(scan) {
86
+ const ephName = scan.ephemeralKeyInfo?.name?.toUpperCase() ?? '';
87
+ const cipherName = scan.cipher?.name?.toUpperCase() ?? '';
88
+ const pqcPatterns = ['KYBER', 'MLKEM', 'ML-KEM'];
89
+ return pqcPatterns.some((p) => ephName.includes(p) || cipherName.includes(p));
90
+ }
91
+ function classifyKeyExchange(scan) {
92
+ if (isPqcKeyExchange(scan)) {
93
+ const name = scan.ephemeralKeyInfo?.name ?? 'PQC hybrid';
94
+ return {
95
+ component: 'keyExchange',
96
+ algorithm: name,
97
+ risk: 'safe',
98
+ reason: 'Post-quantum hybrid key exchange',
99
+ };
100
+ }
101
+ if (!scan.ephemeralKeyInfo) {
102
+ const cipherName = scan.cipher?.name?.toUpperCase() ?? '';
103
+ // TLS 1.2 cipher names include key exchange (e.g., ECDHE-RSA-AES256-GCM-SHA384)
104
+ if (cipherName.includes('ECDHE') || cipherName.includes('X25519')) {
105
+ return {
106
+ component: 'keyExchange',
107
+ algorithm: 'ECDHE (inferred)',
108
+ risk: 'critical',
109
+ reason: "Vulnerable to Shor's algorithm",
110
+ migration: 'ML-KEM (FIPS 203) hybrid key exchange',
111
+ };
112
+ }
113
+ if (cipherName.includes('DHE')) {
114
+ return {
115
+ component: 'keyExchange',
116
+ algorithm: 'DHE (inferred)',
117
+ risk: 'critical',
118
+ reason: "Vulnerable to Shor's algorithm",
119
+ migration: 'ML-KEM (FIPS 203) hybrid key exchange',
120
+ };
121
+ }
122
+ // TLS 1.3 always uses ephemeral key exchange (typically X25519 or ECDHE P-256)
123
+ // but cipher names don't include it — infer from protocol
124
+ if (scan.protocol === 'TLSv1.3') {
125
+ return {
126
+ component: 'keyExchange',
127
+ algorithm: 'X25519 (inferred)',
128
+ risk: 'critical',
129
+ reason: "Vulnerable to Shor's algorithm (TLS 1.3 uses ephemeral ECDHE)",
130
+ migration: 'ML-KEM (FIPS 203) hybrid key exchange',
131
+ };
132
+ }
133
+ return {
134
+ component: 'keyExchange',
135
+ algorithm: 'Unknown',
136
+ risk: 'critical',
137
+ reason: 'Unknown key exchange — assumed vulnerable',
138
+ migration: 'ML-KEM (FIPS 203) hybrid key exchange',
139
+ };
140
+ }
141
+ const type = scan.ephemeralKeyInfo.type.toUpperCase();
142
+ const name = scan.ephemeralKeyInfo.name ?? scan.ephemeralKeyInfo.type;
143
+ if (type === 'ECDH' || type === 'DH') {
144
+ return {
145
+ component: 'keyExchange',
146
+ algorithm: name,
147
+ keySize: scan.ephemeralKeyInfo.size,
148
+ risk: 'critical',
149
+ reason: "Vulnerable to Shor's algorithm",
150
+ migration: 'ML-KEM (FIPS 203) hybrid key exchange',
151
+ };
152
+ }
153
+ return {
154
+ component: 'keyExchange',
155
+ algorithm: name,
156
+ keySize: scan.ephemeralKeyInfo.size,
157
+ risk: 'critical',
158
+ reason: 'Unknown key exchange — assumed vulnerable',
159
+ migration: 'ML-KEM (FIPS 203) hybrid key exchange',
160
+ };
161
+ }
162
+ function classifyCipher(scan) {
163
+ if (!scan.cipher) {
164
+ return {
165
+ component: 'cipher',
166
+ algorithm: 'Unknown',
167
+ risk: 'critical',
168
+ reason: 'Unknown cipher — assumed vulnerable',
169
+ migration: 'Use AES-256-GCM or ChaCha20-Poly1305',
170
+ };
171
+ }
172
+ const name = scan.cipher.name.toUpperCase();
173
+ const bits = scan.cipher.bits;
174
+ if (name.includes('CHACHA20')) {
175
+ return {
176
+ component: 'cipher',
177
+ algorithm: 'ChaCha20-Poly1305',
178
+ keySize: 256,
179
+ risk: 'safe',
180
+ reason: 'Quantum-resistant symmetric cipher',
181
+ };
182
+ }
183
+ if (name.includes('AES')) {
184
+ if (bits >= 256) {
185
+ return {
186
+ component: 'cipher',
187
+ algorithm: `AES-${bits}`,
188
+ keySize: bits,
189
+ risk: 'safe',
190
+ reason: 'Quantum-resistant at current key size',
191
+ };
192
+ }
193
+ return {
194
+ component: 'cipher',
195
+ algorithm: `AES-${bits}`,
196
+ keySize: bits,
197
+ risk: 'moderate',
198
+ reason: "Grover's algorithm reduces to 64-bit effective security",
199
+ migration: 'Upgrade to AES-256',
200
+ };
201
+ }
202
+ return {
203
+ component: 'cipher',
204
+ algorithm: scan.cipher.name,
205
+ keySize: bits,
206
+ risk: 'critical',
207
+ reason: 'Unknown cipher — assumed vulnerable',
208
+ migration: 'Use AES-256-GCM or ChaCha20-Poly1305',
209
+ };
210
+ }
211
+ function extractHash(scan) {
212
+ const name = scan.cipher?.name?.toUpperCase() ?? '';
213
+ const standardName = scan.cipher?.standardName?.toUpperCase() ?? '';
214
+ // Check cipher name first (primary source)
215
+ if (name.includes('SHA384') || name.includes('SHA_384'))
216
+ return 'SHA-384';
217
+ if (name.includes('SHA512') || name.includes('SHA_512'))
218
+ return 'SHA-512';
219
+ if (name.includes('SHA256') || name.includes('SHA_256'))
220
+ return 'SHA-256';
221
+ if (name.endsWith('-SHA') || name.endsWith('_SHA'))
222
+ return 'SHA-1';
223
+ if (name.includes('MD5'))
224
+ return 'MD5';
225
+ // Fallback to standardName
226
+ if (standardName.includes('SHA384') || standardName.includes('SHA_384'))
227
+ return 'SHA-384';
228
+ if (standardName.includes('SHA512') || standardName.includes('SHA_512'))
229
+ return 'SHA-512';
230
+ if (standardName.includes('SHA256') || standardName.includes('SHA_256'))
231
+ return 'SHA-256';
232
+ if (standardName.endsWith('_SHA'))
233
+ return 'SHA-1';
234
+ if (standardName.includes('MD5'))
235
+ return 'MD5';
236
+ return 'Unknown';
237
+ }
238
+ function classifyHash(scan) {
239
+ const hash = extractHash(scan);
240
+ if (hash === 'SHA-384' || hash === 'SHA-512') {
241
+ return {
242
+ component: 'hash',
243
+ algorithm: hash,
244
+ risk: 'safe',
245
+ reason: 'Sufficient post-quantum security margin',
246
+ };
247
+ }
248
+ if (hash === 'SHA-256') {
249
+ return {
250
+ component: 'hash',
251
+ algorithm: hash,
252
+ risk: 'moderate',
253
+ reason: "Grover's reduces to 128-bit effective (still acceptable)",
254
+ migration: 'Consider upgrading to SHA-384',
255
+ };
256
+ }
257
+ if (hash === 'SHA-1') {
258
+ return {
259
+ component: 'hash',
260
+ algorithm: hash,
261
+ risk: 'critical',
262
+ reason: 'Already broken — not quantum-specific',
263
+ migration: 'Upgrade to SHA-256 or SHA-384 immediately',
264
+ };
265
+ }
266
+ if (hash === 'MD5') {
267
+ return {
268
+ component: 'hash',
269
+ algorithm: hash,
270
+ risk: 'critical',
271
+ reason: 'Already broken — not quantum-specific',
272
+ migration: 'Upgrade to SHA-256 or SHA-384 immediately',
273
+ };
274
+ }
275
+ return {
276
+ component: 'hash',
277
+ algorithm: hash,
278
+ risk: 'critical',
279
+ reason: 'Unknown hash — assumed vulnerable',
280
+ migration: 'Use SHA-384 or SHA-512',
281
+ };
282
+ }
283
+ //# sourceMappingURL=classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/scanner/classifier.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,QAAQ,CAAC,IAAmB;IAC1C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE;YACR,gBAAgB,CAAC,IAAI,CAAC;YACtB,mBAAmB,CAAC,IAAI,CAAC;YACzB,mBAAmB,CAAC,IAAI,CAAC;YACzB,cAAc,CAAC,IAAI,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC;SACnB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAmB;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAErC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO;YACL,SAAS,EAAE,UAAU;YACrB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,0BAA0B;SACnC,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO;YACL,SAAS,EAAE,UAAU;YACrB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,kCAAkC;YAC1C,SAAS,EAAE,oBAAoB;SAChC,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,IAAI,SAAS,CAAC;IACtC,OAAO;QACL,SAAS,EAAE,UAAU;QACrB,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,mCAAmC;QAC3C,SAAS,EAAE,gCAAgC;KAC5C,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAmB;IAC9C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACtB,OAAO;YACL,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,wCAAwC;YAChD,SAAS,EAAE,mBAAmB;SAC/B,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC;IAE/C,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACxD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO;YACL,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB;YAC9C,OAAO;YACP,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,4BAA4B;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/E,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACnD,OAAO;YACL,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB;YAC9C,OAAO;YACP,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;YAC7B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,gCAAgC;YACxC,SAAS,EAAE,mBAAmB;SAC/B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,aAAa;QACxB,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB;QAC9C,OAAO;QACP,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,wCAAwC;QAChD,SAAS,EAAE,mBAAmB;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAmB;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IACjE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAE1D,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO,WAAW,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CACrD,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAmB;IAC9C,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,IAAI,YAAY,CAAC;QACzD,OAAO;YACL,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,kCAAkC;SAC3C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAE1D,gFAAgF;QAChF,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClE,OAAO;gBACL,SAAS,EAAE,aAAa;gBACxB,SAAS,EAAE,kBAAkB;gBAC7B,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,gCAAgC;gBACxC,SAAS,EAAE,uCAAuC;aACnD,CAAC;QACJ,CAAC;QAED,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,SAAS,EAAE,aAAa;gBACxB,SAAS,EAAE,gBAAgB;gBAC3B,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,gCAAgC;gBACxC,SAAS,EAAE,uCAAuC;aACnD,CAAC;QACJ,CAAC;QAED,+EAA+E;QAC/E,0DAA0D;QAC1D,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO;gBACL,SAAS,EAAE,aAAa;gBACxB,SAAS,EAAE,mBAAmB;gBAC9B,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,+DAA+D;gBACvE,SAAS,EAAE,uCAAuC;aACnD,CAAC;QACJ,CAAC;QAED,OAAO;YACL,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,2CAA2C;YACnD,SAAS,EAAE,uCAAuC;SACnD,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;IAEtE,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QACrC,OAAO;YACL,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI;YACnC,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,gCAAgC;YACxC,SAAS,EAAE,uCAAuC;SACnD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,aAAa;QACxB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI;QACnC,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,2CAA2C;QACnD,SAAS,EAAE,uCAAuC;KACnD,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,IAAmB;IACzC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,qCAAqC;YAC7C,SAAS,EAAE,sCAAsC;SAClD,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAE9B,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,mBAAmB;YAC9B,OAAO,EAAE,GAAG;YACZ,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,oCAAoC;SAC7C,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;YAChB,OAAO;gBACL,SAAS,EAAE,QAAQ;gBACnB,SAAS,EAAE,OAAO,IAAI,EAAE;gBACxB,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,uCAAuC;aAChD,CAAC;QACJ,CAAC;QAED,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,OAAO,IAAI,EAAE;YACxB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,yDAAyD;YACjE,SAAS,EAAE,oBAAoB;SAChC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;QAC3B,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,qCAAqC;QAC7C,SAAS,EAAE,sCAAsC;KAClD,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAmB;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAEpE,2CAA2C;IAC3C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1E,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1E,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1E,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,OAAO,CAAC;IACnE,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,2BAA2B;IAC3B,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1F,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1F,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1F,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,IAAmB;IACvC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7C,OAAO;YACL,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,yCAAyC;SAClD,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,0DAA0D;YAClE,SAAS,EAAE,+BAA+B;SAC3C,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO;YACL,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,uCAAuC;YAC/C,SAAS,EAAE,2CAA2C;SACvD,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,OAAO;YACL,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,uCAAuC;YAC/C,SAAS,EAAE,2CAA2C;SACvD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,IAAI;QACf,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,mCAAmC;QAC3C,SAAS,EAAE,wBAAwB;KACpC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ClassifiedResult, GradedResult, Grade } from '../types/index.js';
2
+ export declare function grade(classified: ClassifiedResult): GradedResult;
3
+ export declare function shouldFailForGrade(actual: Grade, threshold: Grade): boolean;
4
+ //# sourceMappingURL=grader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grader.d.ts","sourceRoot":"","sources":["../../src/scanner/grader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACN,MAAM,mBAAmB,CAAC;AAM3B,wBAAgB,KAAK,CAAC,UAAU,EAAE,gBAAgB,GAAG,YAAY,CA4ChE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,GAAG,OAAO,CAI3E"}
@@ -0,0 +1,49 @@
1
+ const PQC_KEYWORDS = ['KYBER', 'MLKEM', 'ML-KEM', 'ML-DSA', 'SLH-DSA', 'HQC'];
2
+ const GRADE_ORDER = ['A+', 'A', 'B', 'C', 'D', 'F'];
3
+ export function grade(classified) {
4
+ const { findings } = classified;
5
+ const critical = findings.filter((f) => f.risk === 'critical');
6
+ const moderate = findings.filter((f) => f.risk === 'moderate');
7
+ const safe = findings.filter((f) => f.risk === 'safe');
8
+ const protocolFinding = findings.find((f) => f.component === 'protocol');
9
+ const hashFinding = findings.find((f) => f.component === 'hash');
10
+ let computedGrade;
11
+ if (protocolFinding?.risk === 'critical' || hashFinding?.risk === 'critical') {
12
+ computedGrade = 'F';
13
+ }
14
+ else if (critical.length >= 3) {
15
+ computedGrade = 'D';
16
+ }
17
+ else if (critical.length >= 1) {
18
+ computedGrade = 'C';
19
+ }
20
+ else if (moderate.length >= 1) {
21
+ computedGrade = 'B';
22
+ }
23
+ else {
24
+ const hasPqc = findings.some((f) => PQC_KEYWORDS.some((kw) => f.algorithm.toUpperCase().includes(kw)));
25
+ computedGrade = hasPqc ? 'A+' : 'A';
26
+ }
27
+ const migrationNotes = findings
28
+ .filter((f) => f.migration)
29
+ .map((f) => f.migration);
30
+ return {
31
+ host: classified.host,
32
+ port: classified.port,
33
+ grade: computedGrade,
34
+ findings,
35
+ migrationNotes,
36
+ summary: {
37
+ critical: critical.length,
38
+ moderate: moderate.length,
39
+ safe: safe.length,
40
+ total: findings.length,
41
+ },
42
+ };
43
+ }
44
+ export function shouldFailForGrade(actual, threshold) {
45
+ const actualIndex = GRADE_ORDER.indexOf(actual);
46
+ const thresholdIndex = GRADE_ORDER.indexOf(threshold);
47
+ return actualIndex >= thresholdIndex;
48
+ }
49
+ //# sourceMappingURL=grader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grader.js","sourceRoot":"","sources":["../../src/scanner/grader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TlsScanResult } from '../types/index.js';
2
+ export declare function scanHost(host: string, port: number, timeout: number): Promise<TlsScanResult>;
3
+ //# sourceMappingURL=tls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tls.d.ts","sourceRoot":"","sources":["../../src/scanner/tls.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,CAAC,CA+BxB"}
@@ -0,0 +1,122 @@
1
+ import tls from 'node:tls';
2
+ export function scanHost(host, port, timeout) {
3
+ return new Promise((resolve, reject) => {
4
+ const socket = tls.connect({
5
+ host,
6
+ port,
7
+ rejectUnauthorized: false,
8
+ timeout,
9
+ }, () => {
10
+ try {
11
+ const result = extractTlsData(socket, host, port);
12
+ socket.destroy();
13
+ resolve(result);
14
+ }
15
+ catch (err) {
16
+ socket.destroy();
17
+ reject(err);
18
+ }
19
+ });
20
+ socket.on('error', (err) => {
21
+ socket.destroy();
22
+ reject(err);
23
+ });
24
+ socket.on('timeout', () => {
25
+ socket.destroy();
26
+ reject(new Error(`Connection to ${host}:${port} timed out`));
27
+ });
28
+ });
29
+ }
30
+ function extractTlsData(socket, host, port) {
31
+ const cipher = socket.getCipher();
32
+ const protocol = socket.getProtocol();
33
+ const cert = socket.getPeerCertificate(true);
34
+ let ephemeralKeyInfo = null;
35
+ try {
36
+ const eki = socket.getEphemeralKeyInfo?.();
37
+ if (eki && eki.type) {
38
+ ephemeralKeyInfo = {
39
+ type: eki.type,
40
+ name: eki.name,
41
+ size: eki.size,
42
+ };
43
+ }
44
+ }
45
+ catch {
46
+ // getEphemeralKeyInfo not available — leave null
47
+ }
48
+ let certificate = null;
49
+ if (cert && cert.subject) {
50
+ const cn = typeof cert.subject === 'object'
51
+ ? cert.subject.CN ?? ''
52
+ : String(cert.subject);
53
+ const issuerCN = typeof cert.issuer === 'object'
54
+ ? cert.issuer.CN ?? cert.issuer.O ?? ''
55
+ : String(cert.issuer);
56
+ let publicKeyAlgorithm = 'Unknown';
57
+ const publicKeySize = cert.bits ?? 0;
58
+ const curve = cert.asn1Curve;
59
+ const modulus = cert.modulus;
60
+ const sigAlgorithm = cert.sigalg ?? '';
61
+ // Detect algorithm from cert properties (sigalg is not always available)
62
+ if (modulus) {
63
+ publicKeyAlgorithm = 'RSA';
64
+ }
65
+ else if (curve) {
66
+ publicKeyAlgorithm = 'EC';
67
+ }
68
+ else if (sigAlgorithm.includes('RSA') || sigAlgorithm.includes('rsa')) {
69
+ publicKeyAlgorithm = 'RSA';
70
+ }
71
+ else if (sigAlgorithm.includes('ecdsa') || sigAlgorithm.includes('ECDSA')) {
72
+ publicKeyAlgorithm = 'EC';
73
+ }
74
+ else if (sigAlgorithm.includes('ed25519') || sigAlgorithm.includes('Ed25519')) {
75
+ publicKeyAlgorithm = 'Ed25519';
76
+ }
77
+ else if (sigAlgorithm.includes('ed448') || sigAlgorithm.includes('Ed448')) {
78
+ publicKeyAlgorithm = 'Ed448';
79
+ }
80
+ else if (sigAlgorithm.includes('dsa') || sigAlgorithm.includes('DSA')) {
81
+ publicKeyAlgorithm = 'DSA';
82
+ }
83
+ certificate = {
84
+ subject: cn,
85
+ issuer: issuerCN,
86
+ validFrom: cert.valid_from ?? '',
87
+ validTo: cert.valid_to ?? '',
88
+ serialNumber: cert.serialNumber ?? '',
89
+ fingerprint256: cert.fingerprint256 ?? '',
90
+ sigAlgorithm,
91
+ publicKeyAlgorithm,
92
+ publicKeySize,
93
+ curve,
94
+ };
95
+ }
96
+ return {
97
+ host,
98
+ port,
99
+ protocol: protocol ?? null,
100
+ cipher: cipher
101
+ ? {
102
+ name: cipher.name,
103
+ standardName: cipher.standardName ?? cipher.name,
104
+ version: cipher.version,
105
+ bits: cipher.bits ?? parseCipherBits(cipher.name),
106
+ }
107
+ : null,
108
+ certificate,
109
+ ephemeralKeyInfo,
110
+ };
111
+ }
112
+ function parseCipherBits(cipherName) {
113
+ const upper = cipherName.toUpperCase();
114
+ if (upper.includes('256'))
115
+ return 256;
116
+ if (upper.includes('128'))
117
+ return 128;
118
+ if (upper.includes('CHACHA20'))
119
+ return 256;
120
+ return 0;
121
+ }
122
+ //# sourceMappingURL=tls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tls.js","sourceRoot":"","sources":["../../src/scanner/tls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ export type RiskLevel = 'critical' | 'moderate' | 'safe';
2
+ export type Grade = 'A+' | 'A' | 'B' | 'C' | 'D' | 'F';
3
+ export type ComponentType = 'protocol' | 'certificate' | 'keyExchange' | 'cipher' | 'hash';
4
+ export type OutputFormat = 'terminal' | 'json';
5
+ export interface TlsScanResult {
6
+ host: string;
7
+ port: number;
8
+ protocol: string | null;
9
+ cipher: {
10
+ name: string;
11
+ standardName: string;
12
+ version: string;
13
+ bits: number;
14
+ } | null;
15
+ certificate: {
16
+ subject: string;
17
+ issuer: string;
18
+ validFrom: string;
19
+ validTo: string;
20
+ serialNumber: string;
21
+ fingerprint256: string;
22
+ sigAlgorithm: string;
23
+ publicKeyAlgorithm: string;
24
+ publicKeySize: number;
25
+ curve?: string;
26
+ } | null;
27
+ ephemeralKeyInfo: {
28
+ type: string;
29
+ name?: string;
30
+ size: number;
31
+ } | null;
32
+ }
33
+ export interface ClassifiedFinding {
34
+ component: ComponentType;
35
+ algorithm: string;
36
+ keySize?: number;
37
+ curve?: string;
38
+ risk: RiskLevel;
39
+ reason: string;
40
+ migration?: string;
41
+ }
42
+ export interface ClassifiedResult {
43
+ host: string;
44
+ port: number;
45
+ findings: ClassifiedFinding[];
46
+ }
47
+ export interface GradedResult {
48
+ host: string;
49
+ port: number;
50
+ grade: Grade;
51
+ findings: ClassifiedFinding[];
52
+ migrationNotes: string[];
53
+ summary: {
54
+ critical: number;
55
+ moderate: number;
56
+ safe: number;
57
+ total: number;
58
+ };
59
+ }
60
+ export interface ScanReport {
61
+ version: string;
62
+ timestamp: string;
63
+ results: GradedResult[];
64
+ }
65
+ export interface ScanOptions {
66
+ format: OutputFormat;
67
+ timeout: number;
68
+ verbose: boolean;
69
+ failGrade: Grade;
70
+ file?: string;
71
+ }
72
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzD,MAAM,MAAM,KAAK,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEvD,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,aAAa,GACb,aAAa,GACb,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;IACT,WAAW,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IACT,gBAAgB,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,aAAa,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,KAAK,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,11 +1,57 @@
1
1
  {
2
2
  "name": "postquant",
3
- "version": "0.0.1",
4
- "description": "Post-quantum cryptography audit tool. Scan your code for quantum-vulnerable crypto.",
5
- "main": "index.js",
6
- "bin": { "postquant": "./index.js" },
7
- "keywords": ["post-quantum","cryptography","pqc","security","audit","quantum","nist"],
3
+ "version": "0.1.0",
4
+ "description": "Scan your code and infrastructure for quantum-vulnerable cryptography.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "postquant": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "lint": "tsc --noEmit"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "keywords": [
26
+ "post-quantum",
27
+ "cryptography",
28
+ "pqc",
29
+ "security",
30
+ "audit",
31
+ "quantum",
32
+ "nist",
33
+ "ml-kem",
34
+ "ml-dsa",
35
+ "scanner"
36
+ ],
8
37
  "author": "PostQuant <hello@postquant.dev> (https://postquant.dev)",
9
38
  "license": "MIT",
10
- "homepage": "https://postquant.dev"
39
+ "homepage": "https://postquant.dev",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/postquantdev/postquant.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/postquantdev/postquant/issues"
46
+ },
47
+ "dependencies": {
48
+ "chalk": "^5.6.2",
49
+ "commander": "^14.0.3"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^25.3.3",
53
+ "tsx": "^4.21.0",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^4.0.18"
56
+ }
11
57
  }
package/index.js DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- console.log("postquant v0.0.1 - PQC audit tool. Coming soon. https://postquant.dev");