@blamejs/pki 0.8.59 → 0.8.61

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 (75) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/lib/acme.js +15 -7
  3. package/lib/alt-sig.js +3 -1
  4. package/lib/asn1-der.js +82 -34
  5. package/lib/attrcert-sign.js +19 -16
  6. package/lib/byte-writer.js +63 -13
  7. package/lib/cbor-det.js +9 -3
  8. package/lib/cmc-build.js +26 -18
  9. package/lib/cmp-build.js +35 -33
  10. package/lib/cmp-session.js +19 -9
  11. package/lib/cms-decrypt.js +37 -23
  12. package/lib/cms-digest.js +2 -3
  13. package/lib/cms-encrypt.js +38 -33
  14. package/lib/cms-sign.js +65 -43
  15. package/lib/cms-verify.js +8 -4
  16. package/lib/composite-kem.js +28 -29
  17. package/lib/crl-sign.js +24 -17
  18. package/lib/crmf-sign.js +11 -17
  19. package/lib/csr-sign.js +5 -2
  20. package/lib/ct.js +38 -25
  21. package/lib/est.js +12 -9
  22. package/lib/guard-bytes.js +5 -1
  23. package/lib/guard-crypto.js +506 -14
  24. package/lib/guard-der.js +6 -1
  25. package/lib/guard-intrinsic.js +12 -4
  26. package/lib/guard-list.js +64 -0
  27. package/lib/guard-name.js +1 -1
  28. package/lib/guard-secret.js +3 -2
  29. package/lib/hpke.js +34 -27
  30. package/lib/http-digest.js +5 -7
  31. package/lib/http-transport.js +12 -3
  32. package/lib/inspect.js +10 -2
  33. package/lib/jose.js +3 -1
  34. package/lib/key.js +41 -29
  35. package/lib/lint.js +236 -152
  36. package/lib/mime.js +9 -5
  37. package/lib/ocsp.js +26 -24
  38. package/lib/path-validate.js +43 -13
  39. package/lib/pbes2.js +12 -9
  40. package/lib/pkcs11-uri.js +3 -1
  41. package/lib/pkcs12-build.js +19 -17
  42. package/lib/pki-build.js +17 -13
  43. package/lib/possession.js +3 -1
  44. package/lib/rc2.js +6 -2
  45. package/lib/revocation-fetch.js +78 -19
  46. package/lib/scep.js +21 -14
  47. package/lib/schema-attrcert.js +4 -2
  48. package/lib/schema-c509.js +94 -78
  49. package/lib/schema-cmc.js +5 -2
  50. package/lib/schema-cmp.js +6 -3
  51. package/lib/schema-cms.js +7 -4
  52. package/lib/schema-crl.js +1 -1
  53. package/lib/schema-crmf.js +1 -1
  54. package/lib/schema-csr.js +3 -3
  55. package/lib/schema-engine.js +36 -18
  56. package/lib/schema-pkcs1.js +7 -3
  57. package/lib/schema-pkcs12.js +9 -6
  58. package/lib/schema-pkix.js +19 -3
  59. package/lib/schema-sec1.js +4 -1
  60. package/lib/schema-tsp.js +7 -4
  61. package/lib/shbs.js +10 -9
  62. package/lib/sign-scheme.js +2 -2
  63. package/lib/sigstore.js +9 -9
  64. package/lib/smime.js +19 -16
  65. package/lib/tlog.js +20 -13
  66. package/lib/tuf.js +7 -4
  67. package/lib/validator-cose.js +2 -2
  68. package/lib/validator-keydesc.js +4 -1
  69. package/lib/validator-tls.js +7 -2
  70. package/lib/webauthn-mds.js +3 -7
  71. package/lib/webauthn.js +4 -11
  72. package/lib/webcrypto.js +70 -49
  73. package/lib/x509-sign.js +20 -15
  74. package/package.json +1 -1
  75. package/sbom.cdx.json +6 -6
@@ -98,7 +98,7 @@ function isResourceRefusal(e) {
98
98
  function withResources(ns, source) {
99
99
  if (!source || (source.caps == null && source.budget == null)) return ns;
100
100
  var out = Object.create(null);
101
- var keys = Object.keys(ns);
101
+ var keys = intrinsic.keys(ns);
102
102
  for (var i = 0; i < keys.length; i++) out[keys[i]] = ns[keys[i]];
103
103
  out.caps = source.caps;
104
104
  out.budget = source.budget;
@@ -146,11 +146,11 @@ function integerLeaf() { return { kind: "leaf", read: asn1.read.integer, writ
146
146
  function boolean() { return { kind: "leaf", read: asn1.read.boolean, write: function (v) { return asn1.build.boolean(v); } }; }
147
147
  function octetString() { return { kind: "leaf", read: asn1.read.octetString, write: function (v) { return asn1.build.octetString(v); } }; }
148
148
  function bitString() { return { kind: "leaf", read: function (n) { var b = asn1.read.bitString(n); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.bitString(v.bytes, v.unusedBits); } }; }
149
- function implicitBitString(tag) { return { kind: "leaf", read: function (n) { var b = asn1.read.bitStringImplicit(n, tag); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.contextPrimitive(tag, Buffer.concat([Buffer.from([v.unusedBits]), v.bytes])); } }; }
149
+ function implicitBitString(tag) { return { kind: "leaf", read: function (n) { var b = asn1.read.bitStringImplicit(n, tag); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.contextPrimitive(tag, intrinsic.bufferConcat([intrinsic.bufferFrom([v.unusedBits]), v.bytes])); } }; }
150
150
  function implicitOctetString(tag) { return { kind: "leaf", read: function (n) { return asn1.read.octetStringImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, v); } }; }
151
- function implicitNull(tag) { return { kind: "leaf", read: function (n) { return asn1.read.nullImplicit(n, tag); }, write: function () { return asn1.build.contextPrimitive(tag, Buffer.alloc(0)); } }; }
151
+ function implicitNull(tag) { return { kind: "leaf", read: function (n) { return asn1.read.nullImplicit(n, tag); }, write: function () { return asn1.build.contextPrimitive(tag, intrinsic.bufferAlloc(0)); } }; }
152
152
  function implicitInteger(tag) { return { kind: "leaf", read: function (n) { return asn1.read.integerImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, _implicitIntContent(v)); } }; }
153
- function implicitBoolean(tag) { return { kind: "leaf", read: function (n) { return asn1.read.booleanImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, Buffer.from([v ? 0xff : 0x00])); } }; }
153
+ function implicitBoolean(tag) { return { kind: "leaf", read: function (n) { return asn1.read.booleanImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, intrinsic.bufferFrom([v ? 0xff : 0x00])); } }; }
154
154
  function any() { return { kind: "any" }; }
155
155
  function decode(fn, write) { return { kind: "decode", fn: fn, write: write }; }
156
156
 
@@ -328,7 +328,14 @@ function _walkRepeat(schema, node, ctx) {
328
328
  if (seen.has(key)) _fail(ctx, schema.dupCode || schema.code, "duplicate element " + key);
329
329
  seen.add(key);
330
330
  }
331
- items.push(item);
331
+ /** @internal The element is APPENDED by defining its index. `push` stores, and a store walks the
332
+ * prototype chain for a setter, so an accessor at an array index received each element as the
333
+ * repeat was walked and left the list a hole that reads back whatever its getter answers.
334
+ * `m.items` is what every build() reads its elements out of, and a DN is a SEQUENCE OF RDN:
335
+ * measured, a certificate whose subject is `C=US, ST=California, O=blamejs pki, OU=Test,
336
+ * CN=pkijs.com` parsed with the accessor's value in place of its first RDN, and the parse threw
337
+ * a bare TypeError rather than a typed refusal. */
338
+ intrinsic.append(items, item);
332
339
  }
333
340
  var match = { kind: "repeat", node: node, items: items };
334
341
  if (schema.build) match.result = schema.build(match, ctx);
@@ -336,7 +343,7 @@ function _walkRepeat(schema, node, ctx) {
336
343
  }
337
344
 
338
345
  function _equalsDefault(value, def) {
339
- if (Buffer.isBuffer(value) && Buffer.isBuffer(def)) return value.equals(def);
346
+ if (intrinsic.isBuffer(value) && intrinsic.isBuffer(def)) return intrinsic.bufferEquals(value, def);
340
347
  return value === def;
341
348
  }
342
349
 
@@ -439,7 +446,7 @@ function _encFail(message) { throw new Error("schema.encode: " + message); }
439
446
  function encode(schema, value, ctx) {
440
447
  switch (schema.kind) {
441
448
  case "leaf": return schema.write(value);
442
- case "any": return Buffer.isBuffer(value) ? value : value.bytes;
449
+ case "any": return intrinsic.isBuffer(value) ? value : value.bytes;
443
450
  case "decode":
444
451
  if (typeof schema.write !== "function") _encFail("this decode leaf has no paired encoder (decode(fn, write))");
445
452
  return schema.write(value, ctx);
@@ -453,7 +460,7 @@ function encode(schema, value, ctx) {
453
460
  }
454
461
 
455
462
  function _wrapConstructed(schema, parts) {
456
- if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, Buffer.concat(parts));
463
+ if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, intrinsic.bufferConcat(parts));
457
464
  var mode = schema.assert || "sequence";
458
465
  if (mode === "set") return asn1.build.set(parts);
459
466
  if (mode === "sequence" || mode === "constructed") return asn1.build.sequence(parts);
@@ -469,13 +476,17 @@ function _encodeSeq(schema, value, ctx) {
469
476
  for (var f = 0; f < schema.fields.length; f++) {
470
477
  var fld = schema.fields[f];
471
478
  if (fld.fkind === "required") {
472
- parts.push(encode(fld.schema, value[fld.name], ctx));
479
+ /** @internal Each field is APPENDED by defining its index, for the reason the repeat walk is:
480
+ * `push` stores, a store consults a setter inherited at the index, and these parts are
481
+ * concatenated in order into the structure this encoder emits. Measured, an accessor at
482
+ * index 0 put its own TLV where the first field belongs. */
483
+ intrinsic.append(parts, encode(fld.schema, value[fld.name], ctx));
473
484
  } else if (fld.fkind === "optional") {
474
485
  if (_present(value[fld.name])) {
475
486
  var enc = encode(fld.schema, value[fld.name], ctx);
476
487
  var isDefault = fld.hasDefault && fld.def !== undefined &&
477
- enc.equals(encode(fld.schema, fld.def, ctx));
478
- if (!isDefault) parts.push(fld.explicit ? asn1.build.explicit(fld.tag, enc) : enc);
488
+ intrinsic.bufferEquals(enc, encode(fld.schema, fld.def, ctx));
489
+ if (!isDefault) intrinsic.append(parts, fld.explicit ? asn1.build.explicit(fld.tag, enc) : enc);
479
490
  }
480
491
  } else if (fld.fkind === "trailing") {
481
492
  var members = guardList.sortedCopy(fld.members, function (a, b) { return a.tag - b.tag; });
@@ -483,7 +494,7 @@ function _encodeSeq(schema, value, ctx) {
483
494
  var mm = members[i];
484
495
  if (_present(value[mm.name])) {
485
496
  var menc = encode(mm.schema, value[mm.name], ctx);
486
- parts.push(mm.explicit ? asn1.build.explicit(mm.tag, menc) : menc);
497
+ intrinsic.append(parts, mm.explicit ? asn1.build.explicit(mm.tag, menc) : menc);
487
498
  }
488
499
  }
489
500
  } else {
@@ -494,17 +505,21 @@ function _encodeSeq(schema, value, ctx) {
494
505
  }
495
506
 
496
507
  function _encodeRepeat(schema, items, ctx) {
497
- if (!Array.isArray(items)) _encFail("a repeat value must be an array");
508
+ if (!intrinsic.isArray(items)) _encFail("a repeat value must be an array");
498
509
  if (schema.min != null && items.length < schema.min) {
499
510
  _encFail("this repeat requires at least " + schema.min + " element(s) but got " + items.length);
500
511
  }
501
512
  if (schema.max != null && items.length > schema.max) {
502
513
  _encFail("this repeat caps at " + schema.max + " element(s) but got " + items.length);
503
514
  }
504
- var parts = items.map(function (it) { return encode(schema.item, it, ctx); });
515
+ /** @internal The elements are mapped through the captured operation, which builds its result by
516
+ * defining each index on a plain array. `Array.prototype.map` is replaceable and reads the
517
+ * receiver's `Symbol.species` to construct what it returns, so a caller's array could both
518
+ * choose the encoded elements and hand this encoder a result object of its own class. */
519
+ var parts = intrinsic.mapList(items, function (it) { return encode(schema.item, it, ctx); });
505
520
  if (schema.unique) {
506
521
  var seen = new Set();
507
- parts.forEach(function (tlv) {
522
+ intrinsic.forEach(parts, function (tlv) {
508
523
  // allow:bare-decode a round trip through the codec on a TLV this encoder just produced.
509
524
  var item = { node: asn1.decode(tlv) };
510
525
  item.value = walk(schema.item, item.node, ctx);
@@ -517,7 +532,7 @@ function _encodeRepeat(schema, items, ctx) {
517
532
  * is the engine's own SET OF emission, so whatever decides "before" decides the bytes every schema
518
533
  * built on it emits. */
519
534
  if (schema.derSetOrder) parts = guardList.sortedCopy(parts, intrinsic.compare);
520
- if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, Buffer.concat(parts));
535
+ if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, intrinsic.bufferConcat(parts));
521
536
  return schema.assert === "set" ? asn1.build.set(parts) : asn1.build.sequence(parts);
522
537
  }
523
538
 
@@ -586,11 +601,14 @@ function isUniversal(node, tagNumber) {
586
601
  function isContext(node, tagNumber) {
587
602
  return !!node && node.tagClass === "context" && node.tagNumber === tagNumber;
588
603
  }
604
+ /** @internal Both read the OWN elements of the tag list. `indexOf` is specified in terms of
605
+ * HasProperty, so a list with a hole at an index answers from the array prototype, and the list
606
+ * here is an allow-list deciding whether a node's tag is one a schema accepts. */
589
607
  function isUniversalOneOf(node, tagNumbers) {
590
- return !!node && node.tagClass === "universal" && tagNumbers.indexOf(node.tagNumber) !== -1;
608
+ return !!node && node.tagClass === "universal" && intrinsic.ownIndexOf(tagNumbers, node.tagNumber) !== -1;
591
609
  }
592
610
  function isContextOneOf(node, tagNumbers) {
593
- return !!node && node.tagClass === "context" && tagNumbers.indexOf(node.tagNumber) !== -1;
611
+ return !!node && node.tagClass === "context" && intrinsic.ownIndexOf(tagNumbers, node.tagNumber) !== -1;
594
612
  }
595
613
  function isContextInRange(node, min, max) {
596
614
  return !!node && node.tagClass === "context" && node.tagNumber >= min && node.tagNumber <= max;
@@ -264,11 +264,15 @@ function encode(key) {
264
264
  var infos = key.otherPrimeInfos;
265
265
  if (intrinsic.isArray(infos) && infos.length > 0) {
266
266
  var rows = [];
267
+ /** @internal Both appends define the index. A store at an index a list has no own property at
268
+ * walks the prototype chain for a setter, so an accessor there took the element and the list
269
+ * read back whatever its getter answers; `kids` holds nine own slots here, so index nine is
270
+ * such a store. These are the bytes a private key encodes to. */
267
271
  for (var i = 0; i < infos.length; i++) {
268
- rows[i] = asn1.build.sequence([asn1.build.integer(infos[i].prime),
269
- asn1.build.integer(infos[i].exponent), asn1.build.integer(infos[i].coefficient)]);
272
+ intrinsic.append(rows, asn1.build.sequence([asn1.build.integer(infos[i].prime),
273
+ asn1.build.integer(infos[i].exponent), asn1.build.integer(infos[i].coefficient)]));
270
274
  }
271
- kids[9] = asn1.build.sequence(rows);
275
+ intrinsic.append(kids, asn1.build.sequence(rows));
272
276
  }
273
277
  return asn1.build.sequence(kids);
274
278
  }
@@ -47,6 +47,9 @@ var cms = require("./schema-cms.js");
47
47
  var pkcs8 = require("./schema-pkcs8.js");
48
48
  var frameworkError = require("./framework-error.js");
49
49
  var guard = require("./guard-all.js");
50
+ /** @internal The append this module's lists are built with: `push` stores at the index and a store
51
+ * consults a setter inherited there, which takes the element being appended. */
52
+ var _push = guard.list.append;
50
53
 
51
54
  var Pkcs12Error = frameworkError.Pkcs12Error;
52
55
  var PemError = frameworkError.PemError;
@@ -181,7 +184,7 @@ var SAFE_BAG = schema.seq([
181
184
  var items = m.fields.bagAttributes.value.items;
182
185
  for (var i = 0; i < items.length; i++) {
183
186
  var a = items[i].value.result;
184
- attributes.push(a);
187
+ _push(attributes, a);
185
188
  if (a.type === OID_FRIENDLY_NAME) {
186
189
  if (seen[a.type] || a.values.length !== 1) throw ctx.E("pkcs12/bad-friendly-name", "friendlyName carries exactly one BMPString value (PKCS#9 SINGLE VALUE)");
187
190
  friendlyName = _bmpValue(a.values[0], ctx);
@@ -319,7 +322,7 @@ function walkSafeContents(der, ctx) {
319
322
  var walked = schema.walk(SAFE_CONTENTS, pkix.decodeNested(der, ns, "a SafeContents", { ber: true }), ns);
320
323
  var state = { budget: { remaining: C.LIMITS.PKCS12_MAX_REDECODES }, bagDepth: 0 };
321
324
  var bags = [];
322
- for (var i = 0; i < walked.items.length; i++) bags.push(_buildBag(walked.items[i].value.result, state, ns));
325
+ for (var i = 0; i < walked.items.length; i++) _push(bags, _buildBag(walked.items[i].value.result, state, ns));
323
326
  return bags;
324
327
  }
325
328
 
@@ -334,12 +337,12 @@ function _dispatchSafes(asMatch, state, ctx) {
334
337
  budget: state.budget, budgetCode: "pkcs12/too-deep",
335
338
  });
336
339
  for (var j = 0; j < contents.items.length; j++) {
337
- safeBags.push(_buildBag(contents.items[j].value.result, state, ctx));
340
+ _push(safeBags, _buildBag(contents.items[j].value.result, state, ctx));
338
341
  }
339
342
  } else if (el.contentType === OID_ENCRYPTED_DATA) {
340
- encryptedSafes.push({ type: "encryptedData", content: _privacySafe(cms.walkEncryptedData(el.innerNode, ctx), ctx) });
343
+ _push(encryptedSafes, { type: "encryptedData", content: _privacySafe(cms.walkEncryptedData(el.innerNode, ctx), ctx) });
341
344
  } else if (el.contentType === OID_ENVELOPED_DATA) {
342
- encryptedSafes.push({ type: "envelopedData", content: _privacySafe(cms.walkEnvelopedData(el.innerNode, ctx), ctx), envelopedDataDer: el.innerNode.bytes });
345
+ _push(encryptedSafes, { type: "envelopedData", content: _privacySafe(cms.walkEnvelopedData(el.innerNode, ctx), ctx), envelopedDataDer: el.innerNode.bytes });
343
346
  } else {
344
347
  throw ctx.E("pkcs12/bad-safe-contentinfo-type", "an AuthenticatedSafe element must be id-data, id-encryptedData, or id-envelopedData (RFC 7292 sec. 4.1), got " +
345
348
  (ctx.oid.name(el.contentType) || el.contentType));
@@ -391,7 +394,7 @@ function _buildBag(rec, state, ctx) {
391
394
  bag.nested = [];
392
395
  var nestedMatch = schema.walk(SAFE_CONTENTS, rec.valueNode, ctx);
393
396
  for (var i = 0; i < nestedMatch.items.length; i++) {
394
- bag.nested.push(_buildBag(nestedMatch.items[i].value.result, nestedState, ctx));
397
+ _push(bag.nested, _buildBag(nestedMatch.items[i].value.result, nestedState, ctx));
395
398
  }
396
399
  return bag;
397
400
  }
@@ -11,8 +11,17 @@ var intrinsic = require("./guard-intrinsic");
11
11
  var frameworkError = require("./framework-error");
12
12
  var _hasOwn = intrinsic.hasOwn;
13
13
  var _forEach = intrinsic.forEach;
14
- var _map = intrinsic.map;
15
- var _push = intrinsic.push;
14
+ /** @internal `mapList`, not the captured `map`. `Array.prototype.map` is specified to build its
15
+ * result through `ArraySpeciesCreate`, which reads the receiver's `constructor` and then that
16
+ * constructor's `Symbol.species`, so a getter installed on `Array.prototype.constructor` runs
17
+ * caller code with the list being mapped as its `this` on every call. Capturing the method closes
18
+ * which function runs, not the protocol it consults. Measured on a certificate parse: the
19
+ * extension-list build was reached that way. `mapList` defines each index on a plain array. */
20
+ var _map = intrinsic.mapList;
21
+ /** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
22
+ * setter, so an accessor there takes the element being appended. The lists built here are the parsed
23
+ * members every format module reads its fields from. `append` defines the index. */
24
+ var _push = intrinsic.append;
16
25
  var _join = intrinsic.join;
17
26
  var _stringify = intrinsic.stringify;
18
27
  var _String = intrinsic.String;
@@ -51,7 +60,14 @@ function _hasNonWhitespace(s) {
51
60
  for (var i = 0; i < s.length; i++) { if (!_isJsWhitespace(_charCodeAt(s, i))) return true; }
52
61
  return false;
53
62
  }
54
- function _charTable(chars) { var t = []; for (var i = 0; i < chars.length; i++) t[_charCodeAt(chars, i)] = true; return t; }
63
+ /** @internal The table has NO PROTOTYPE, because it is deliberately sparse: it holds an entry for
64
+ * each character it allows and nothing at the codes it does not, and `_allCharsIn` below reads it at
65
+ * the code of each character it is asked about. Built as an array literal, every code outside the
66
+ * allowed set was a hole, so a value installed at that index on `Array.prototype` answered the
67
+ * check: measured, `Array.prototype[47] = true` made `pki.acme.keyAuthorization` accept a challenge
68
+ * token containing `/`, which the base64url set does not allow, instead of refusing it with
69
+ * `acme/bad-token`. The same helper in lib/guard-name.js has always been written this way. */
70
+ function _charTable(chars) { var t = _create(null); for (var i = 0; i < chars.length; i++) t[_charCodeAt(chars, i)] = true; return t; }
55
71
  function _allCharsIn(s, table) {
56
72
  if (s.length === 0) return false;
57
73
  for (var i = 0; i < s.length; i++) { if (!table[_charCodeAt(s, i)]) return false; }
@@ -210,7 +210,10 @@ function encode(key) {
210
210
  asn1.build.octetString(key.privateKey),
211
211
  asn1.build.explicit(0, asn1.build.oid(curveOid))];
212
212
  if (key.publicKey !== undefined && key.publicKey !== null) {
213
- kids[3] = asn1.build.explicit(1, asn1.build.bitString(key.publicKey, 0));
213
+ /** @internal Appended by defining the index. `kids` holds three own slots above, so assigning at
214
+ * index three is a store, and a store walks the prototype chain for a setter: an accessor there
215
+ * would take the public key out of the structure this encodes. */
216
+ intrinsic.append(kids, asn1.build.explicit(1, asn1.build.bitString(key.publicKey, 0)));
214
217
  }
215
218
  return asn1.build.sequence(kids);
216
219
  }
package/lib/schema-tsp.js CHANGED
@@ -43,6 +43,9 @@ var smime = require("./schema-smime");
43
43
  var cms = require("./schema-cms");
44
44
  var frameworkError = require("./framework-error");
45
45
  var guard = require("./guard-all");
46
+ /** @internal The append this module's lists are built with: `push` stores at the index and a store
47
+ * consults a setter inherited there, which takes the element being appended. */
48
+ var _push = guard.list.append;
46
49
 
47
50
  var TspError = frameworkError.TspError;
48
51
  var PemError = frameworkError.PemError;
@@ -196,7 +199,7 @@ function _namedBits(bytes) {
196
199
  if ((bytes[i >> 3] >> (7 - (i & 7))) & 1) {
197
200
  var nm = FAILURE_BITS[i];
198
201
  if (!nm) throw NS.E("tsp/bad-failinfo", "unsupported PKIFailureInfo bit " + i + " (RFC 3161 sec. 2.4.2)");
199
- out.push(nm);
202
+ _push(out, nm);
200
203
  }
201
204
  }
202
205
  return out;
@@ -525,8 +528,8 @@ function essDigest(name) {
525
528
  var xof = ESS_XOF_BYTES[name];
526
529
  /** @internal One read of the name answers both whether the digest can be computed and how to
527
530
  * compute it, so the hash every candidate is put through is the one that read settled. */
528
- return function () {
529
- return xof ? nodeCrypto.createHash(name, { outputLength: xof }) : nodeCrypto.createHash(name);
531
+ return function (bytes) {
532
+ return xof ? guard.crypto.xof(name, bytes, xof) : guard.crypto.digest(name, bytes);
530
533
  };
531
534
  }
532
535
 
@@ -576,7 +579,7 @@ function _essNamedCertificate(token, attr) {
576
579
  for (var j = 0; j < certs.length; j++) {
577
580
  var element = certs[j];
578
581
  if (!element || element.tagClass !== "universal" || !Buffer.isBuffer(element.bytes)) continue;
579
- var actual = digest().update(element.bytes).digest();
582
+ var actual = digest(element.bytes);
580
583
  if (actual.length === want.length && guard.bytes.compare(actual, want) === 0) return element.bytes;
581
584
  }
582
585
  return null;
package/lib/shbs.js CHANGED
@@ -21,9 +21,12 @@
21
21
  * @card Verify HSS/LMS signatures (post-quantum, CNSA 2.0 firmware signing).
22
22
  */
23
23
 
24
- var nodeCrypto = require("crypto");
25
24
  var frameworkError = require("./framework-error");
26
25
  var guard = require("./guard-all");
26
+ /** @internal The append every list here is built with: `push` stores at the index and a store
27
+ * consults a setter inherited there, and these lists are the authentication path and the one-time
28
+ * values a hash-based signature is formed from. */
29
+ var _push = guard.list.append;
27
30
  var constants = require("./constants");
28
31
 
29
32
  var ShbsError = frameworkError.ShbsError;
@@ -78,11 +81,9 @@ function _lmotsSet(code) {
78
81
  }
79
82
 
80
83
  function _hash(family, n, parts) {
81
- var h;
82
- if (family === "shake256") h = nodeCrypto.createHash("shake256", { outputLength: n });
83
- else h = nodeCrypto.createHash("sha256");
84
- for (var i = 0; i < parts.length; i++) h.update(parts[i]);
85
- var d = h.digest();
84
+ var d = family === "shake256"
85
+ ? guard.crypto.digestParts("shake256", parts, n)
86
+ : guard.crypto.digestParts("sha256", parts);
86
87
  return (family === "shake256" || n === 32) ? d : d.subarray(0, n);
87
88
  }
88
89
 
@@ -124,7 +125,7 @@ function _lmotsKc(otsSet, I, q, C, y, message) {
124
125
  var a = _coef(Qc, i, w);
125
126
  var tmp = y[i];
126
127
  for (var j = a; j < (1 << w) - 1; j++) tmp = _hash(f, n, [I, qb, u16(i), u8(j), tmp]);
127
- z.push(tmp);
128
+ _push(z,tmp);
128
129
  }
129
130
  return _hash(f, n, z);
130
131
  }
@@ -148,11 +149,11 @@ function _lmsVerify(pubBytes, message, sigBytes) {
148
149
  var n = otsSet.n, p = otsSet.p;
149
150
  var C = sr.take(n);
150
151
  var y = [];
151
- for (var yi = 0; yi < p; yi++) y.push(sr.take(n));
152
+ for (var yi = 0; yi < p; yi++) _push(y,sr.take(n));
152
153
  var sigLmsType = sr.u32();
153
154
  if (sigLmsType !== lmsSet.code) return false;
154
155
  var path = [];
155
- for (var pi = 0; pi < h; pi++) path.push(sr.take(m));
156
+ for (var pi = 0; pi < h; pi++) _push(path,sr.take(m));
156
157
  if (!sr.atEnd()) throw _err("shbs/bad-signature", "LMS signature has " + sr.remaining() + " trailing byte(s)");
157
158
  if (q >= Math.pow(2, h)) return false;
158
159
 
@@ -359,14 +359,14 @@ function _keyTypeAccepts(reported, wanted) {
359
359
  }
360
360
 
361
361
  function _assertKeyObjectMatchesScheme(key, scheme, E) {
362
- var reported = key.asymmetricKeyType;
362
+ var reported = guard.crypto.keyType(key);
363
363
  var wanted = NODE_KEY_TYPE[scheme.imp.name] || _toLowerCase(_String(scheme.imp.name));
364
364
  if (!_keyTypeAccepts(reported, wanted)) {
365
365
  throw E("bad-input", "the signer KeyObject algorithm (" + reported +
366
366
  ") does not match the certificate's key algorithm (" + scheme.imp.name + ")");
367
367
  }
368
368
  if (scheme.imp.namedCurve) {
369
- var details = key.asymmetricKeyDetails;
369
+ var details = guard.crypto.keyDetails(key);
370
370
  var curve = details && details.namedCurve;
371
371
  if (curve !== NODE_CURVE[scheme.imp.namedCurve]) {
372
372
  throw E("bad-input", "the signer KeyObject curve (" + curve +
package/lib/sigstore.js CHANGED
@@ -28,7 +28,6 @@
28
28
  * @card Verify an npm --provenance Sigstore bundle offline (DSSE + Fulcio + Rekor + SLSA).
29
29
  */
30
30
 
31
- var nodeCrypto = require("crypto");
32
31
  var frameworkError = require("./framework-error");
33
32
  var constants = require("./constants");
34
33
  var asn1 = require("./asn1-der");
@@ -227,8 +226,8 @@ function _assertKeyDetailsParameters(want, leafSpki, declared) {
227
226
  if (want.bits !== undefined) {
228
227
  var bits;
229
228
  try {
230
- bits = guard.crypto.publicKey({ key: leafSpki.bytes, format: "der", type: "spki" })
231
- .asymmetricKeyDetails.modulusLength;
229
+ bits = guard.crypto.keyDetails(
230
+ guard.crypto.publicKey({ key: leafSpki.bytes, format: "der", type: "spki" })).modulusLength;
232
231
  } catch (_e) { bits = null; } // allow:swallow-unverified -- a key that will not import has no modulus size to match, and the mismatch below is the verdict
233
232
  if (bits !== want.bits) {
234
233
  throw _err("sigstore/entry-mismatch", "the Rekor entry states the signing key is " +
@@ -709,13 +708,14 @@ function _chainDers(vm) {
709
708
  }
710
709
 
711
710
  function _rawVerify(keyObj, data, derSig) {
712
- var t = keyObj.asymmetricKeyType;
711
+ var t = guard.crypto.keyType(keyObj);
713
712
  if (t === "ed25519" || t === "ed448") {
714
713
  var edSpki = guard.crypto.exportKey(keyObj, { type: "spki", format: "der" });
715
714
  edwardsPoint.validateSpki(edSpki, t === "ed25519" ? 6 : 7, SigstoreError, "sigstore/bad-key");
716
715
  return guard.crypto.verify(null, data, keyObj, derSig);
717
716
  }
718
- var crv = keyObj.asymmetricKeyDetails && keyObj.asymmetricKeyDetails.namedCurve;
717
+ var keyObjDetails = guard.crypto.keyDetails(keyObj);
718
+ var crv = keyObjDetails && keyObjDetails.namedCurve;
719
719
  var hash = crv === "secp384r1" ? "sha384" : (crv === "secp521r1" ? "sha512" : "sha256");
720
720
  return guard.crypto.verify(hash, data, { key: keyObj, dsaEncoding: "der" }, derSig);
721
721
  }
@@ -723,7 +723,7 @@ function _pubFromSpki(spkiDer, label) {
723
723
  var key;
724
724
  try { key = guard.crypto.publicKey({ key: spkiDer, format: "der", type: "spki" }); }
725
725
  catch (e) { throw _err("sigstore/bad-key", "invalid " + label + " public key", e); }
726
- var t = key.asymmetricKeyType;
726
+ var t = guard.crypto.keyType(key);
727
727
  if (t === "ed25519" || t === "ed448") {
728
728
  edwardsPoint.validateSpki(spkiDer, t === "ed25519" ? 6 : 7, SigstoreError, "sigstore/bad-key");
729
729
  }
@@ -735,7 +735,7 @@ function _parseCert(der, label) {
735
735
  }
736
736
 
737
737
 
738
- function _sha256(buf) { return nodeCrypto.createHash("sha256").update(buf).digest(); }
738
+ function _sha256(buf) { return guard.crypto.digest("sha256", buf); }
739
739
 
740
740
  function _toMs(x) {
741
741
  if (x == null) return null;
@@ -1109,7 +1109,7 @@ function _bindHashedRekordV002Entry(body, arm, leafDer, contentType, payloadType
1109
1109
  }
1110
1110
  var digest = _b64(data.digest, "hashedRekordV002.data.digest");
1111
1111
  if (contentType === "dsseEnvelope") {
1112
- var computed = nodeCrypto.createHash(alg.node).update(pae(payloadType, payload)).digest();
1112
+ var computed = guard.crypto.digest(alg.node, pae(payloadType, payload));
1113
1113
  if (!guard.crypto.constantTimeEqual(computed, digest)) {
1114
1114
  throw _err("sigstore/entry-mismatch", "the Rekor entry digest is not the hash of this envelope's " +
1115
1115
  "signing preimage, so the entry records a different signature than the bundle carries");
@@ -1831,7 +1831,7 @@ async function verifyBundle(bundle, opts) {
1831
1831
  var artifactDigests = intrinsic.create(null);
1832
1832
  function _artifactDigest(nodeName) {
1833
1833
  if (!intrinsic.hasOwn(artifactDigests, nodeName)) {
1834
- artifactDigests[nodeName] = nodeCrypto.createHash(nodeName).update(artifact).digest();
1834
+ artifactDigests[nodeName] = guard.crypto.digest(nodeName, artifact);
1835
1835
  }
1836
1836
  return artifactDigests[nodeName];
1837
1837
  }
package/lib/smime.js CHANGED
@@ -41,10 +41,13 @@ var schemaX509 = require("./schema-x509.js");
41
41
  var pkix = require("./schema-pkix.js");
42
42
  var oid = require("./oid.js");
43
43
  var guard = require("./guard-all.js");
44
+ /** @internal The append every list here is built with: `push` stores at the index and a store
45
+ * consults a setter inherited there, and these lists become the headers and parts a signed or
46
+ * encrypted message carries. */
47
+ var _push = guard.list.append;
44
48
  var pkiBuild = require("./pki-build.js");
45
49
  var C = require("./constants.js");
46
50
  var nodeUtil = require("util");
47
- var nodeCrypto = require("crypto");
48
51
 
49
52
  var SmimeError = frameworkError.SmimeError;
50
53
 
@@ -118,13 +121,13 @@ function _hpHeaderList(headers) {
118
121
  if (!h || typeof h !== "object") throw _err("smime/bad-input", "each opts.headers entry must be { name, value }");
119
122
  var name = h.name, v = h.value;
120
123
  if (typeof name !== "string") throw _err("smime/bad-input", "each opts.headers entry must be { name, value }");
121
- out.push({ name: name, value: v == null ? "" : String(v) });
124
+ _push(out,{ name: name, value: v == null ? "" : String(v) });
122
125
  });
123
126
  } else if (typeof headers === "object") {
124
127
  var hn = guard.identifier.optionNames(headers);
125
128
  for (var hi = 0; hi < hn.length; hi++) {
126
129
  var hv = headers[hn[hi]];
127
- out.push({ name: hn[hi], value: hv == null ? "" : String(hv) });
130
+ _push(out,{ name: hn[hi], value: hv == null ? "" : String(hv) });
128
131
  }
129
132
  } else {
130
133
  throw _err("smime/bad-input", "opts.headers must be an object or an array of { name, value }");
@@ -155,9 +158,9 @@ function _outerHeaderList(list, mode, hcp) {
155
158
  list.forEach(function (h) {
156
159
  if (mode === "cipher") {
157
160
  var v = _applyHcp(h.name, h.value, policy);
158
- if (v !== null) out.push({ name: h.name, value: v });
161
+ if (v !== null) _push(out,{ name: h.name, value: v });
159
162
  } else {
160
- out.push({ name: h.name, value: h.value });
163
+ _push(out,{ name: h.name, value: h.value });
161
164
  }
162
165
  });
163
166
  return out;
@@ -171,9 +174,9 @@ function _protectedInnerEntity(content, opts, mode, hpList, outerList) {
171
174
  if (cty != null && mime.hasParam(cty, "hp")) throw _err("smime/bad-input", "opts.contentType must not set the hp parameter -- header protection sets it (hp=" + guard.text.showValue(mode) + ")");
172
175
  var ct = (cty || "text/plain; charset=utf-8") + "; hp=\"" + mode + "\"";
173
176
  var fields = [{ name: "Content-Type", value: ct }, { name: "Content-Transfer-Encoding", value: _is7bit(raw) ? "7bit" : "8bit" }];
174
- hpList.forEach(function (h) { fields.push(h); });
177
+ hpList.forEach(function (h) { _push(fields,h); });
175
178
  if (mode === "cipher") {
176
- outerList.forEach(function (h) { fields.push({ name: "HP-Outer", value: h.name + ": " + h.value }); });
179
+ outerList.forEach(function (h) { _push(fields,{ name: "HP-Outer", value: h.name + ": " + h.value }); });
177
180
  }
178
181
  return mime.buildEntity(fields, raw, SmimeError, "smime/bad-header");
179
182
  }
@@ -227,7 +230,7 @@ function _contentTypeLines(s) {
227
230
  var lines = [], lineStart = 0;
228
231
  while (lineStart <= s.length) {
229
232
  var line = _contentTypeLineAt(s, lineStart);
230
- if (line !== null) lines.push(line);
233
+ if (line !== null) _push(lines,line);
231
234
  var nl = s.indexOf("\n", lineStart);
232
235
  if (nl === -1) break;
233
236
  lineStart = nl + 1;
@@ -274,11 +277,11 @@ function _extractProtected(headerList) {
274
277
  if (_isStructural(h.lname)) return;
275
278
  if (h.lname === "hp-outer") {
276
279
  var ci = h.rawValue.indexOf(":");
277
- if (ci >= 0) refouter.push({ name: h.rawValue.slice(0, ci).trim().toLowerCase(), value: h.rawValue.slice(ci + 1).trim() });
280
+ if (ci >= 0) _push(refouter,{ name: h.rawValue.slice(0, ci).trim().toLowerCase(), value: h.rawValue.slice(ci + 1).trim() });
278
281
  return;
279
282
  }
280
283
  var val = _utf8Header(h.rawValue);
281
- entries.push({ name: h.name, value: val, raw: h.rawValue });
284
+ _push(entries,{ name: h.name, value: val, raw: h.rawValue });
282
285
  if (seen[h.lname]) { dup = h.name; if (RFC5322_SINGLETON.has(h.lname)) dupSingleton = h.name; }
283
286
  seen[h.lname] = 1;
284
287
  protectedHeaders[h.name] = val;
@@ -297,7 +300,7 @@ function _computeConfidential(entries, refouter) {
297
300
  entries.forEach(function (e) {
298
301
  var m = byName.get(e.name.toLowerCase()), val = e.raw.trim(), n = (m && m.get(val)) || 0;
299
302
  if (n > 0) { m.set(val, n - 1); return; }
300
- if (!seen[e.name]) { seen[e.name] = 1; confidential.push(e.name); }
303
+ if (!seen[e.name]) { seen[e.name] = 1; _push(confidential,e.name); }
301
304
  });
302
305
  return confidential;
303
306
  }
@@ -305,7 +308,7 @@ function _computeConfidential(entries, refouter) {
305
308
  function _computeFromMismatch(innerFrom, outerEnt) {
306
309
  if (innerFrom == null) return null;
307
310
  var outerFroms = [];
308
- outerEnt.headers.forEach(function (h) { if (h.lname === "from") outerFroms.push(h.value.trim()); });
311
+ outerEnt.headers.forEach(function (h) { if (h.lname === "from") _push(outerFroms,h.value.trim()); });
309
312
  return outerFroms.length !== 1 || outerFroms[0] !== innerFrom.trim();
310
313
  }
311
314
 
@@ -315,7 +318,7 @@ function _isCryptoLayer(type) {
315
318
 
316
319
  function _outerRefouter(outerEnt) {
317
320
  var r = [];
318
- outerEnt.headers.forEach(function (h) { if (!_isStructural(h.lname) && h.lname !== "hp-outer") r.push({ name: h.lname, value: h.rawValue.trim() }); });
321
+ outerEnt.headers.forEach(function (h) { if (!_isStructural(h.lname) && h.lname !== "hp-outer") _push(r,{ name: h.lname, value: h.rawValue.trim() }); });
319
322
  return r;
320
323
  }
321
324
 
@@ -572,7 +575,7 @@ function _cmsSignOpts(opts, detached) {
572
575
  function _micName(name) { return name ? (MICALG[name] || name) : null; }
573
576
  function _micalgSet(value) {
574
577
  var seen = [];
575
- String(value).split(",").forEach(function (m) { var t = m.trim().toLowerCase(); if (t && seen.indexOf(t) < 0) seen.push(t); });
578
+ String(value).split(",").forEach(function (m) { var t = m.trim().toLowerCase(); if (t && seen.indexOf(t) < 0) _push(seen,t); });
576
579
  return seen.sort().join(",");
577
580
  }
578
581
  function _micalgOf(p7Der) {
@@ -582,12 +585,12 @@ function _micalgOf(p7Der) {
582
585
  var out = [];
583
586
  (parsed.signerInfos || []).forEach(function (si) {
584
587
  var mic = _micName(si.digestAlgorithm && si.digestAlgorithm.name);
585
- if (mic && out.indexOf(mic) < 0) out.push(mic);
588
+ if (mic && out.indexOf(mic) < 0) _push(out,mic);
586
589
  });
587
590
  return out.length ? out.sort().join(",") : null;
588
591
  }
589
592
 
590
- function _boundary() { return "----=_pki_smime_" + nodeCrypto.randomBytes(18).toString("hex"); }
593
+ function _boundary() { return "----=_pki_smime_" + guard.crypto.randomBytes(18).toString("hex"); }
591
594
 
592
595
  function _wrap64Crlf(s) {
593
596
  var out = "";
package/lib/tlog.js CHANGED
@@ -69,9 +69,10 @@ var _strSlice = intrinsic.uncurry(String.prototype.slice);
69
69
  var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
70
70
  var _arrSlice = intrinsic.arraySlice;
71
71
  var _join = intrinsic.join;
72
- var _push = intrinsic.push;
72
+ /** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
73
+ * setter, so an accessor there takes the element being appended. `append` defines it. */
74
+ var _push = intrinsic.append;
73
75
  var _pop = intrinsic.pop;
74
- var _unshift = intrinsic.unshift;
75
76
  var _bufToString = intrinsic.bufToString;
76
77
  var _bufferFrom = intrinsic.bufferFrom;
77
78
  var _byteLength = intrinsic.byteLength;
@@ -298,12 +299,13 @@ function _resolveKey(keyName, publicKey) {
298
299
  throw _err("tlog/bad-input", "publicKey must be the raw " + ED25519_RAW_BYTES +
299
300
  " Ed25519 bytes or a SubjectPublicKeyInfo, got " + bytes.length + " bytes", e);
300
301
  }
301
- var type = key.asymmetricKeyType;
302
+ var type = guard.crypto.keyType(key);
302
303
  if (type === "ed25519") {
303
304
  return _edKey(name, bytes, _subarray(bytes, bytes.length - ED25519_RAW_BYTES));
304
305
  }
305
306
  if (type === "ec") {
306
- var curve = key.asymmetricKeyDetails && key.asymmetricKeyDetails.namedCurve;
307
+ var keyDetails = guard.crypto.keyDetails(key);
308
+ var curve = keyDetails && keyDetails.namedCurve;
307
309
  if (EC_CURVES[curve] !== 1) {
308
310
  throw _err("tlog/bad-input", "a signed note names no key-ID derivation for the elliptic curve " +
309
311
  guard.text.showValue(_stringOf(curve)));
@@ -798,20 +800,25 @@ var MAX_INDEX_SEGMENTS = (function () {
798
800
  return count;
799
801
  })();
800
802
 
803
+ /** @internal The segments are counted and then APPENDED most-significant first, by defining each
804
+ * index. Prepending STORES at an index, and a store walks the prototype chain for a setter, so an
805
+ * accessor inherited at an array index took each segment and left the list reading back its getter's
806
+ * value; the `x` prefix was then applied by a read-modify-write through the same hole. These
807
+ * segments are the path a tile is requested from, so the list decides which bytes a verification
808
+ * reads. */
801
809
  function _indexPath(index) {
802
810
  var n = guard.range.uint64(index, _err, "tlog/bad-tile", "a tile index");
803
- var segments = [];
804
- var rest = n;
805
811
  var thousand = 1000n;
806
- for (;;) {
807
- var part = rest % thousand;
808
- var text = _stringOf(part);
812
+ var count = 1;
813
+ for (var probe = n / thousand; probe > 0n; probe = probe / thousand) count++;
814
+ var segments = [];
815
+ for (var k = count - 1; k >= 0; k--) {
816
+ var scale = 1n;
817
+ for (var p = 0; p < k; p++) scale = scale * thousand;
818
+ var text = _stringOf((n / scale) % thousand);
809
819
  while (text.length < TILE_SEGMENT_DIGITS) text = "0" + text;
810
- _unshift(segments, text);
811
- rest = rest / thousand;
812
- if (rest === 0n) break;
820
+ _push(segments, k === 0 ? text : "x" + text);
813
821
  }
814
- for (var i = 0; i < segments.length - 1; i++) segments[i] = "x" + segments[i];
815
822
  return _join(segments, "/");
816
823
  }
817
824