cryptoserve 0.1.1 → 0.1.3

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.
@@ -487,7 +487,15 @@ function calculateQuantumScore(libraries, classifications) {
487
487
 
488
488
  if (total === 0) return 100.0;
489
489
 
490
- let score = (safe / total) * 100;
490
+ // Two scoring approaches:
491
+ // - Ratio: safe / total (good for large samples)
492
+ // - Penalty: 100 - 30 per vulnerable (good for small samples)
493
+ // Small samples (≤3 algorithms) produce extreme ratios (1/1 = 0% or 100%),
494
+ // so use whichever approach gives the more representative score.
495
+ const ratioScore = (safe / total) * 100;
496
+ const penaltyScore = Math.max(0, 100 - vulnerable * 30);
497
+ let score = total <= 3 ? Math.max(ratioScore, penaltyScore) : ratioScore;
498
+
491
499
  if (classifications.some(c => c.category === 'pqc')) {
492
500
  score = Math.min(100, score + 20);
493
501
  }
package/lib/scanner.mjs CHANGED
@@ -51,9 +51,15 @@ const IMPORT_PATTERNS = [
51
51
  { pattern: /createDecipheriv\s*\(/g, lib: 'node:crypto', detail: 'cipher' },
52
52
  { pattern: /createSign\s*\(/g, lib: 'node:crypto', detail: 'signature' },
53
53
  { pattern: /createVerify\s*\(/g, lib: 'node:crypto', detail: 'signature' },
54
+ { pattern: /createHash\s*\(/g, lib: 'node:crypto', detail: 'hash' },
55
+ { pattern: /createHmac\s*\(/g, lib: 'node:crypto', detail: 'hmac' },
54
56
  { pattern: /generateKeyPair(?:Sync)?\s*\(/g, lib: 'node:crypto', detail: 'keygen' },
57
+ { pattern: /createDiffieHellman(?:Group)?\s*\(/g, lib: 'node:crypto', detail: 'keyagreement' },
58
+ { pattern: /createECDH\s*\(/g, lib: 'node:crypto', detail: 'keyagreement' },
55
59
  { pattern: /scrypt(?:Sync)?\s*\(/g, lib: 'node:crypto', detail: 'kdf' },
56
60
  { pattern: /pbkdf2(?:Sync)?\s*\(/g, lib: 'node:crypto', detail: 'kdf' },
61
+ { pattern: /randomBytes\s*\(/g, lib: 'node:crypto', detail: 'random' },
62
+ { pattern: /randomUUID\s*\(/g, lib: 'node:crypto', detail: 'random' },
57
63
  { pattern: /createCipher\s*\(/g, lib: 'node:crypto', detail: 'DEPRECATED-no-iv' },
58
64
  { pattern: /CryptoJS\./g, lib: 'crypto-js' },
59
65
  { pattern: /forge\.\w+/g, lib: 'node-forge' },
@@ -69,6 +75,10 @@ const ALGO_LITERALS = [
69
75
  { pattern: /['"`]sha(?:256|384|512|1)['"`]/gi, algo: 'SHA-256' },
70
76
  { pattern: /['"`](?:HS|RS|ES|PS)(?:256|384|512)['"`]/gi, algo: 'RS256' },
71
77
  { pattern: /['"`]ed25519['"`]/gi, algo: 'Ed25519' },
78
+ { pattern: /['"`]x25519['"`]/gi, algo: 'X25519' },
79
+ { pattern: /['"`](?:ecdsa|ecdh|ec|secp256k1|secp384r1|prime256v1)['"`]/gi, algo: 'ECDSA' },
80
+ { pattern: /['"`](?:rsa|rsa-pss)['"`]/gi, algo: 'RSA' },
81
+ { pattern: /['"`](?:dsa)['"`]/gi, algo: 'DSA' },
72
82
  { pattern: /minVersion:\s*['"`]TLSv1\.[0-3]['"`]/g, algo: 'TLS' },
73
83
  { pattern: /['"`](?:md5|MD5)['"`]/g, algo: 'MD5' },
74
84
  { pattern: /['"`](?:des|DES|3des|3DES|des-ede3)['"`]/gi, algo: 'DES' },
@@ -169,9 +179,26 @@ export function scanProject(projectDir) {
169
179
  filesScanned: 0,
170
180
  };
171
181
 
172
- // 1. Scan package.json for crypto dependencies
173
- const pkgPath = join(projectDir, 'package.json');
174
- if (existsSync(pkgPath)) {
182
+ // 1. Scan package.json for crypto dependencies (root + monorepo workspaces)
183
+ const pkgPaths = [join(projectDir, 'package.json')];
184
+ // Check common monorepo locations for nested package.json files
185
+ const monorepoGlobs = ['apps', 'packages', 'libs', 'modules', 'services'];
186
+ for (const sub of monorepoGlobs) {
187
+ const subDir = join(projectDir, sub);
188
+ try {
189
+ const entries = readdirSync(subDir, { withFileTypes: true });
190
+ for (const entry of entries) {
191
+ if (entry.isDirectory()) {
192
+ const nested = join(subDir, entry.name, 'package.json');
193
+ if (existsSync(nested)) pkgPaths.push(nested);
194
+ }
195
+ }
196
+ } catch { /* dir doesn't exist */ }
197
+ }
198
+
199
+ const seenPkgs = new Set();
200
+ for (const pkgPath of pkgPaths) {
201
+ if (!existsSync(pkgPath)) continue;
175
202
  try {
176
203
  const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
177
204
  const allDeps = {
@@ -180,7 +207,8 @@ export function scanProject(projectDir) {
180
207
  };
181
208
 
182
209
  for (const [name, version] of Object.entries(allDeps)) {
183
- if (name in CRYPTO_PACKAGES) {
210
+ if (name in CRYPTO_PACKAGES && !seenPkgs.has(name)) {
211
+ seenPkgs.add(name);
184
212
  const info = CRYPTO_PACKAGES[name];
185
213
  results.libraries.push({
186
214
  name,
@@ -188,7 +216,7 @@ export function scanProject(projectDir) {
188
216
  algorithms: info.algorithms,
189
217
  quantumRisk: info.quantumRisk,
190
218
  category: info.category,
191
- source: 'package.json',
219
+ source: pkgPath.replace(projectDir + '/', ''),
192
220
  });
193
221
  }
194
222
  }
@@ -281,11 +309,17 @@ export function scanProject(projectDir) {
281
309
  if (seenImports.has('node:crypto:') || seenImports.has('node:crypto:cipher')) {
282
310
  if (!nodeCryptoAlgos.includes('AES')) nodeCryptoAlgos.push('AES');
283
311
  }
312
+ if (seenImports.has('node:crypto:') || seenImports.has('node:crypto:hash') || seenImports.has('node:crypto:hmac')) {
313
+ if (!nodeCryptoAlgos.includes('SHA-256')) nodeCryptoAlgos.push('SHA-256');
314
+ }
284
315
  if (seenImports.has('node:crypto:signature')) {
285
316
  if (!nodeCryptoAlgos.includes('RSA')) nodeCryptoAlgos.push('RSA');
286
317
  }
318
+ if (seenImports.has('node:crypto:keygen') || seenImports.has('node:crypto:keyagreement')) {
319
+ if (!nodeCryptoAlgos.includes('ECDSA')) nodeCryptoAlgos.push('ECDSA');
320
+ }
287
321
  if (seenImports.has('node:crypto:kdf')) {
288
- nodeCryptoAlgos.push('scrypt');
322
+ if (!nodeCryptoAlgos.includes('scrypt')) nodeCryptoAlgos.push('scrypt');
289
323
  }
290
324
 
291
325
  if (nodeCryptoAlgos.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptoserve",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "CryptoServe CLI - Cryptographic scanning, PQC analysis, encryption, and local key management",
5
5
  "type": "module",
6
6
  "bin": {