@quantakrypto/core 0.5.0 → 0.7.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.
Files changed (51) hide show
  1. package/dist/crypto-agility.d.ts +158 -0
  2. package/dist/crypto-agility.d.ts.map +1 -0
  3. package/dist/crypto-agility.js +285 -0
  4. package/dist/crypto-agility.js.map +1 -0
  5. package/dist/dependencies.d.ts.map +1 -1
  6. package/dist/dependencies.js +180 -18
  7. package/dist/dependencies.js.map +1 -1
  8. package/dist/detectors/source.d.ts.map +1 -1
  9. package/dist/detectors/source.js +52 -0
  10. package/dist/detectors/source.js.map +1 -1
  11. package/dist/hndl.d.ts +241 -0
  12. package/dist/hndl.d.ts.map +1 -0
  13. package/dist/hndl.js +752 -0
  14. package/dist/hndl.js.map +1 -0
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +6 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/mandates.d.ts +138 -0
  20. package/dist/mandates.d.ts.map +1 -0
  21. package/dist/mandates.js +228 -0
  22. package/dist/mandates.js.map +1 -0
  23. package/dist/parallel.d.ts.map +1 -1
  24. package/dist/parallel.js +22 -23
  25. package/dist/parallel.js.map +1 -1
  26. package/dist/report.d.ts +8 -0
  27. package/dist/report.d.ts.map +1 -1
  28. package/dist/report.js +75 -19
  29. package/dist/report.js.map +1 -1
  30. package/dist/types.d.ts +1 -1
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/types.js.map +1 -1
  33. package/dist/version.d.ts +1 -1
  34. package/dist/version.js +1 -1
  35. package/dist/version.js.map +1 -1
  36. package/dist/walk.d.ts +31 -1
  37. package/dist/walk.d.ts.map +1 -1
  38. package/dist/walk.js +30 -9
  39. package/dist/walk.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/crypto-agility.ts +407 -0
  42. package/src/dependencies.ts +182 -16
  43. package/src/detectors/source.ts +62 -0
  44. package/src/hndl.ts +1012 -0
  45. package/src/index.ts +71 -0
  46. package/src/mandates.ts +365 -0
  47. package/src/parallel.ts +21 -20
  48. package/src/report.ts +84 -19
  49. package/src/types.ts +9 -1
  50. package/src/version.ts +1 -1
  51. package/src/walk.ts +47 -10
@@ -47,6 +47,15 @@ import { CWE_BROKEN_CRYPTO, CWE_CERT_VALIDATION, CWE_WEAK_STRENGTH } from "../cw
47
47
  // (ordered alternation would otherwise match `rsa` and reject the `-pss` tail).
48
48
  const RE_GENERATE_KEYPAIR =
49
49
  /generateKeyPair(?:Sync)?\s*\(\s*['"`](rsa-pss|rsa|ec|dsa|dh|x25519|x448|ed25519|ed448)['"`]/g;
50
+ // Variable-typed key generation: `generateKeyPair(kind, …)` where the algorithm
51
+ // argument is an IDENTIFIER (a variable), not a quoted literal, so the concrete
52
+ // family is unknown at scan time but a classical key is still being generated.
53
+ // The lookbehind anchors the call to a word boundary so it does not fire inside
54
+ // a longer identifier (e.g. `myGenerateKeyPair(`); the first argument must be a
55
+ // bare identifier immediately followed by `,` or `)` so a quoted-literal call
56
+ // (handled by RE_GENERATE_KEYPAIR) never matches here.
57
+ const RE_GENERATE_KEYPAIR_VAR =
58
+ /(?<![\w$])generateKeyPair(?:Sync)?\s*\(\s*([A-Za-z_$][\w$]*)\s*[,)]/g;
50
59
 
51
60
  /** Per-key-type classification for `generateKeyPair(Sync)('<type>', …)`. Hoisted
52
61
  * to module scope so the direct matcher AND the import-alias pass (below) share
@@ -177,6 +186,20 @@ function escapeRe(s: string): string {
177
186
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
178
187
  }
179
188
  const RE_CREATE_SIGN_VERIFY = /create(?:Sign|Verify)\s*\(/g;
189
+ // Computed-member (bracket) access to a Node `crypto` method:
190
+ // `crypto['createSign'](…)`, `c["createECDH"](…)`. Bracket access defeats the
191
+ // dotted-call regexes above (which require `name(`), so match a quoted method
192
+ // name inside a `[ '…' ]( ` computed call and route it to the right rule. The
193
+ // method names here take no key-type argument, so no argument parsing is needed;
194
+ // `generateKeyPair(Sync)` bracket access is handled separately (it carries the
195
+ // key-type literal). None of these overlap the dotted regexes (those require the
196
+ // name immediately before `(`, whereas here it is followed by a closing quote).
197
+ const RE_BRACKET_CRYPTO_METHOD =
198
+ /\[\s*['"`](createSign|createVerify|createECDH|createDiffieHellman|createDiffieHellmanGroup|publicEncrypt|privateDecrypt)['"`]\s*\]\s*\(/g;
199
+ // `crypto['generateKeyPairSync']('rsa', …)`: bracket access carrying the quoted
200
+ // key-type literal, classified exactly like the dotted `generateKeyPair` call.
201
+ const RE_BRACKET_KEYGEN =
202
+ /\[\s*['"`]generateKeyPair(?:Sync)?['"`]\s*\]\s*\(\s*['"`](rsa-pss|rsa|ec|dsa|dh|x25519|x448|ed25519|ed448)['"`]/g;
180
203
  // One-shot crypto.sign/verify(algorithm, data, key). A LOOKBEHIND (not a
181
204
  // consumed char) anchors it so it doesn't fire inside identifiers like `assign(`
182
205
  // or `createSign(` (handled by the dedicated createSign/createVerify rule) —
@@ -375,6 +398,28 @@ const nodeCryptoDetector: Detector = {
375
398
  pushKeygenFinding(findings, m[1], file, content, m.index, m[0].length);
376
399
  });
377
400
 
401
+ // generateKeyPair(Sync)(<variable>, …): key type passed as a variable, so the
402
+ // family is unknown; emit the generic keygen rule (unknown / key-exchange /
403
+ // HNDL-conservative) rather than missing the classical key generation.
404
+ eachMatch(RE_GENERATE_KEYPAIR_VAR, content, (m) => {
405
+ findings.push(
406
+ findingFromRule(
407
+ RULE_NODE_KEYGEN,
408
+ { file, content, index: m.index, matchLength: m[0].length },
409
+ {
410
+ title: "Classical key generation (variable key type)",
411
+ message:
412
+ "Generates a classical asymmetric key pair (key type passed as a variable), which is not quantum-safe.",
413
+ },
414
+ ),
415
+ );
416
+ });
417
+
418
+ // Bracket (computed-member) key generation: crypto['generateKeyPairSync']('rsa').
419
+ eachMatch(RE_BRACKET_KEYGEN, content, (m) => {
420
+ pushKeygenFinding(findings, m[1], file, content, m.index, m[0].length);
421
+ });
422
+
378
423
  // Import-alias resolution: follow `import { generateKeyPairSync as gk }` (and
379
424
  // the CommonJS destructure-rename) so an aliased call still detects. Only the
380
425
  // keygen / ECDH / DH constructors are resolved — their classification is
@@ -432,6 +477,23 @@ const nodeCryptoDetector: Detector = {
432
477
  );
433
478
  });
434
479
 
480
+ // Bracket (computed-member) access to argument-free crypto methods:
481
+ // crypto['createSign'](…), c["createECDH"](…). Route each to its rule.
482
+ eachMatch(RE_BRACKET_CRYPTO_METHOD, content, (m) => {
483
+ const loc = { file, content, index: m.index, matchLength: m[0].length };
484
+ const method = m[1];
485
+ if (method === "createSign" || method === "createVerify") {
486
+ findings.push(findingFromRule(RULE_NODE_SIGN, loc));
487
+ } else if (method === "createECDH") {
488
+ findings.push(findingFromRule(RULE_NODE_ECDH, loc));
489
+ } else if (method === "publicEncrypt" || method === "privateDecrypt") {
490
+ findings.push(findingFromRule(RULE_NODE_RSA_ENCRYPT, loc));
491
+ } else {
492
+ // createDiffieHellman / createDiffieHellmanGroup: finite-field DH.
493
+ findings.push(findingFromRule(RULE_NODE_DH, loc));
494
+ }
495
+ });
496
+
435
497
  // One-shot crypto.sign(algorithm, data, key) / crypto.verify(...) (Node ≥ 12).
436
498
  eachMatch(RE_ONESHOT_SIGN_VERIFY, content, (m) => {
437
499
  findings.push(