@blamejs/pki 0.8.59 → 0.8.60

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 (63) hide show
  1. package/CHANGELOG.md +33 -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 +12 -9
  9. package/lib/cmp-build.js +35 -33
  10. package/lib/cmp-session.js +19 -9
  11. package/lib/cms-decrypt.js +22 -8
  12. package/lib/cms-encrypt.js +23 -17
  13. package/lib/cms-sign.js +65 -43
  14. package/lib/cms-verify.js +8 -4
  15. package/lib/crl-sign.js +24 -17
  16. package/lib/csr-sign.js +5 -2
  17. package/lib/ct.js +27 -16
  18. package/lib/est.js +12 -9
  19. package/lib/guard-bytes.js +5 -1
  20. package/lib/guard-der.js +6 -1
  21. package/lib/guard-intrinsic.js +12 -4
  22. package/lib/guard-list.js +64 -0
  23. package/lib/guard-name.js +1 -1
  24. package/lib/hpke.js +10 -3
  25. package/lib/http-transport.js +12 -3
  26. package/lib/inspect.js +10 -2
  27. package/lib/jose.js +3 -1
  28. package/lib/lint.js +236 -152
  29. package/lib/mime.js +9 -5
  30. package/lib/ocsp.js +25 -22
  31. package/lib/path-validate.js +43 -13
  32. package/lib/pbes2.js +6 -2
  33. package/lib/pkcs11-uri.js +3 -1
  34. package/lib/pkcs12-build.js +14 -11
  35. package/lib/pki-build.js +14 -10
  36. package/lib/possession.js +3 -1
  37. package/lib/rc2.js +6 -2
  38. package/lib/revocation-fetch.js +78 -19
  39. package/lib/scep.js +14 -6
  40. package/lib/schema-attrcert.js +4 -2
  41. package/lib/schema-c509.js +94 -78
  42. package/lib/schema-cmc.js +5 -2
  43. package/lib/schema-cmp.js +6 -3
  44. package/lib/schema-cms.js +7 -4
  45. package/lib/schema-crl.js +1 -1
  46. package/lib/schema-crmf.js +1 -1
  47. package/lib/schema-csr.js +3 -3
  48. package/lib/schema-engine.js +36 -18
  49. package/lib/schema-pkcs1.js +7 -3
  50. package/lib/schema-pkcs12.js +9 -6
  51. package/lib/schema-pkix.js +19 -3
  52. package/lib/schema-sec1.js +4 -1
  53. package/lib/schema-tsp.js +4 -1
  54. package/lib/shbs.js +7 -3
  55. package/lib/smime.js +18 -14
  56. package/lib/tlog.js +17 -11
  57. package/lib/tuf.js +3 -1
  58. package/lib/validator-keydesc.js +4 -1
  59. package/lib/validator-tls.js +7 -2
  60. package/lib/webcrypto.js +9 -3
  61. package/lib/x509-sign.js +20 -15
  62. package/package.json +1 -1
  63. package/sbom.cdx.json +6 -6
package/lib/cms-sign.js CHANGED
@@ -15,6 +15,12 @@ var webcrypto = require("./webcrypto");
15
15
  var signScheme = require("./sign-scheme");
16
16
  var guard = require("./guard-all");
17
17
  var intrinsic = require("./guard-intrinsic");
18
+ /** @internal `append`, not a captured `push`: appending with `push` STORES at the index, and a store
19
+ * walks the prototype chain for a setter, so an accessor installed at an array index receives each
20
+ * element as it is appended and can define something else in its place. The lists built here become
21
+ * a message's signed attributes, its certificate set and its signer infos. `append` defines the
22
+ * index on the array itself. */
23
+ var _push = intrinsic.append;
18
24
  /** @internal `resolve` and `all` build their promise from the RECEIVER, so reading the global binding
19
25
  * at the call hands the construction to whatever that binding holds. Each signer's digest and
20
26
  * signature are awaited through one of these, and a replacement that settles without awaiting emits a
@@ -73,7 +79,11 @@ function _digest(digestName, content) {
73
79
 
74
80
 
75
81
  function _skiValue(cert) {
76
- var ext = (cert.extensions || []).filter(function (e) { return e.oid === OID_SKI; })[0];
82
+ /** @internal The selection returns the first matching row or null, because `filter(...)[0]` indexes
83
+ * a result that is EMPTY when the extension is absent, and index 0 of an empty array answers from
84
+ * the array prototype: the refusal below would then not be reached for a certificate that carries
85
+ * no SKI. */
86
+ var ext = guard.list.firstMatch(cert.extensions || [], function (e) { return e.oid === OID_SKI; });
77
87
  if (!ext) throw _err("cms/no-ski", "a subjectKeyIdentifier signer identifier requires the signer certificate to carry an SKI extension");
78
88
  try { return asn1.read.octetString(asn1.decode(ext.value)); }
79
89
  catch (e) { throw _err("cms/no-ski", "the signer certificate's subjectKeyIdentifier extension value is not an OCTET STRING", e); }
@@ -216,10 +226,10 @@ async function _finishSignerInfo(rc, md, content, eContentType, opts) {
216
226
  { type: O("contentType"), values: [b.oid(eContentType)] },
217
227
  { type: O("messageDigest"), values: [b.octetString(md)] },
218
228
  ];
219
- if (opts.signingTime !== false) intrinsic.push(pairs, { type: O("signingTime"), values: [_timeValue(opts.signingTime)] });
229
+ if (opts.signingTime !== false) _push(pairs, { type: O("signingTime"), values: [_timeValue(opts.signingTime)] });
220
230
  var apOid = cms.algorithmProtectionOid(opts.algorithmProtection, _err);
221
231
  if (apOid) {
222
- intrinsic.push(pairs, _algorithmProtectionPair(apOid,
232
+ _push(pairs, _algorithmProtectionPair(apOid,
223
233
  rc.scheme.digestAlgId, rc.scheme.sigAlgId, 1));
224
234
  }
225
235
  pairs = intrinsic.concat(pairs, _resolveAttrPairs(opts.additionalSignedAttributes, "a signed attribute value"));
@@ -230,10 +240,13 @@ async function _finishSignerInfo(rc, md, content, eContentType, opts) {
230
240
  var sig = await signScheme.signOverTbs(rc.scheme, rc.soKey, signedBytes, _signE);
231
241
  await _assertKeyMatchesSpki(rc.keyOnly, rc.soKey, rc.soSpki, rc.scheme, sig, signedBytes, rc.cert);
232
242
  var fields = [b.integer(BigInt(rc.version)), rc.sid, rc.scheme.digestAlgId];
233
- if (toSign.wire) intrinsic.push(fields, toSign.wire);
234
- intrinsic.push(fields, rc.scheme.sigAlgId, b.octetString(sig));
243
+ if (toSign.wire) _push(fields, toSign.wire);
244
+ /** @internal Two appends, because `append` takes one value where `push` took many: the algorithm
245
+ * identifier and the signature it describes are adjacent fields of the same SignerInfo. */
246
+ _push(fields, rc.scheme.sigAlgId);
247
+ _push(fields, b.octetString(sig));
235
248
  var ua = _buildUnsignedAttrs(opts.unsignedAttributes);
236
- if (ua) intrinsic.push(fields, ua);
249
+ if (ua) _push(fields, ua);
237
250
  return { si: b.sequence(fields), digestAlgId: rc.scheme.digestAlgId, version: rc.version, certDer: rc.certDer };
238
251
  }
239
252
 
@@ -367,7 +380,7 @@ async function _signStream(stream, signers, opts) {
367
380
  if (opts.signingTime != null && opts.signingTime !== false) guard.time.assertEncodable(opts.signingTime, _err, "cms/bad-input", "signingTime");
368
381
  var rcs = intrinsic.map(list, function (s) { return _resolveSignerContext(s, opts); });
369
382
  var digestNames = [], seenDigest = intrinsic.create(null);
370
- intrinsic.forEach(rcs, function (r) { if (!seenDigest[r.scheme.digest]) { seenDigest[r.scheme.digest] = 1; intrinsic.push(digestNames, r.scheme.digest); } });
383
+ intrinsic.forEach(rcs, function (r) { if (!seenDigest[r.scheme.digest]) { seenDigest[r.scheme.digest] = 1; _push(digestNames, r.scheme.digest); } });
371
384
  var wcNames = intrinsic.map(digestNames, function (n) { return DIGEST_HASH[n]; });
372
385
  var digests;
373
386
  try {
@@ -379,7 +392,7 @@ async function _signStream(stream, signers, opts) {
379
392
  intrinsic.forEach(digestNames, function (n, i) { byName[n] = intrinsic.bufferFrom(digests[i]); });
380
393
  var built = [];
381
394
  for (var _ip = 0; _ip < rcs.length; _ip++) {
382
- intrinsic.push(built, await _finishSignerInfo(rcs[_ip], byName[rcs[_ip].scheme.digest], null, eContentType, opts));
395
+ _push(built, await _finishSignerInfo(rcs[_ip], byName[rcs[_ip].scheme.digest], null, eContentType, opts));
383
396
  }
384
397
  return _assembleSignedData(built, eContentType, opts, null);
385
398
  }
@@ -420,19 +433,19 @@ function _sign(content, signers, opts) {
420
433
 
421
434
  function _assembleSignedData(built, eContentType, opts, contentBuf) {
422
435
  var seen = intrinsic.create(null), digestAlgs = [];
423
- intrinsic.forEach(built, function (x) { var k = intrinsic.bufToString(x.digestAlgId, "hex"); if (!seen[k]) { seen[k] = 1; intrinsic.push(digestAlgs, x.digestAlgId); } });
436
+ intrinsic.forEach(built, function (x) { var k = intrinsic.bufToString(x.digestAlgId, "hex"); if (!seen[k]) { seen[k] = 1; _push(digestAlgs, x.digestAlgId); } });
424
437
  var v3 = intrinsic.some(built, function (x) { return x.version === 3; }) || eContentType !== OID_DATA;
425
438
  var version = v3 ? 3 : 1;
426
439
  var encapFields = [b.oid(eContentType)];
427
- if (!opts.detached) intrinsic.push(encapFields, b.explicit(0, b.octetString(contentBuf)));
440
+ if (!opts.detached) _push(encapFields, b.explicit(0, b.octetString(contentBuf)));
428
441
  var encap = b.sequence(encapFields);
429
442
  var sdFields = [b.integer(BigInt(version)), b.set(digestAlgs), encap];
430
443
  if (opts.certificates !== false) {
431
444
  var certDers = intrinsic.sort(_dedupe(intrinsic.filter(intrinsic.map(built, function (x) { return x.certDer; }),
432
445
  function (d) { return d != null; })), intrinsic.compare);
433
- if (certDers.length) intrinsic.push(sdFields, b.contextConstructed(0, intrinsic.bufferConcat(certDers)));
446
+ if (certDers.length) _push(sdFields, b.contextConstructed(0, intrinsic.bufferConcat(certDers)));
434
447
  }
435
- intrinsic.push(sdFields, b.set(intrinsic.map(built, function (x) { return x.si; })));
448
+ _push(sdFields, b.set(intrinsic.map(built, function (x) { return x.si; })));
436
449
  var signedData = b.sequence(sdFields);
437
450
  var contentInfo = b.sequence([b.oid(OID_SIGNED_DATA), b.explicit(0, signedData)]);
438
451
  return opts.pem ? pkix.pemEncode(contentInfo, "CMS", frameworkError.PemError) : contentInfo;
@@ -450,7 +463,7 @@ function _digestAlgIdentifier(der) {
450
463
 
451
464
  function _dedupe(ders) {
452
465
  var seen = intrinsic.create(null), out = [];
453
- intrinsic.forEach(ders, function (d) { var k = intrinsic.bufToString(d, "hex"); if (!seen[k]) { seen[k] = 1; intrinsic.push(out, d); } });
466
+ intrinsic.forEach(ders, function (d) { var k = intrinsic.bufToString(d, "hex"); if (!seen[k]) { seen[k] = 1; _push(out, d); } });
454
467
  return out;
455
468
  }
456
469
 
@@ -496,9 +509,9 @@ function certsOnly(certs, opts) {
496
509
  var crlDers = intrinsic.sort(_dedupe(intrinsic.map(crlList, function (c) { return _normEntityDer(c, "a CRL", "X509 CRL", _parseCrl); })), intrinsic.compare);
497
510
  var encap = b.sequence([b.oid(OID_DATA)]);
498
511
  var sdFields = [b.integer(1n), b.set([]), encap];
499
- if (certDers.length) intrinsic.push(sdFields, b.contextConstructed(0, intrinsic.bufferConcat(certDers)));
500
- if (crlDers.length) intrinsic.push(sdFields, b.contextConstructed(1, intrinsic.bufferConcat(crlDers)));
501
- intrinsic.push(sdFields, b.set([]));
512
+ if (certDers.length) _push(sdFields, b.contextConstructed(0, intrinsic.bufferConcat(certDers)));
513
+ if (crlDers.length) _push(sdFields, b.contextConstructed(1, intrinsic.bufferConcat(crlDers)));
514
+ _push(sdFields, b.set([]));
502
515
  var signedData = b.sequence(sdFields);
503
516
  var contentInfo = b.sequence([b.oid(OID_SIGNED_DATA), b.explicit(0, signedData)]);
504
517
  return opts.pem ? pkix.pemEncode(contentInfo, "CMS", frameworkError.PemError) : contentInfo;
@@ -512,7 +525,7 @@ function _toBuf(v, what) {
512
525
 
513
526
  function _resolveSignerIndices(spec, n) {
514
527
  if (spec == null) { if (n < 1) throw _err("cms/bad-input", "the SignedData carries no SignerInfo to countersign"); return [0]; }
515
- if (spec === "all") { var all = []; for (var i = 0; i < n; i++) all.push(i); return all; }
528
+ if (spec === "all") { var all = []; for (var i = 0; i < n; i++) _push(all, i); return all; }
516
529
  var arr = Array.isArray(spec) ? spec : [spec];
517
530
  if (!arr.length) throw _err("cms/bad-input", "signerIndex must select at least one signer");
518
531
  arr.forEach(function (i) { if (typeof i !== "number" || !Number.isInteger(i) || i < 0 || i >= n) throw _err("cms/bad-input", "signerIndex out of range: " + i); });
@@ -534,10 +547,10 @@ function _buildCountersignature(targetSigOctets, countersigner, opts) {
534
547
  if (opts.signedAttributes === false) return null;
535
548
  return intrinsic.chain(_digest(scheme.digest, targetSigOctets), function (md) {
536
549
  var pairs = [{ type: O("messageDigest"), values: [b.octetString(md)] }];
537
- if (opts.signingTime !== false) pairs.push({ type: O("signingTime"), values: [_timeValue(opts.signingTime)] });
550
+ if (opts.signingTime !== false) _push(pairs, { type: O("signingTime"), values: [_timeValue(opts.signingTime)] });
538
551
  var csApOid = cms.algorithmProtectionOid(opts.algorithmProtection, _err);
539
552
  if (csApOid) {
540
- intrinsic.push(pairs, _algorithmProtectionPair(csApOid, scheme.digestAlgId, scheme.sigAlgId, 1));
553
+ _push(pairs, _algorithmProtectionPair(csApOid, scheme.digestAlgId, scheme.sigAlgId, 1));
541
554
  }
542
555
  var extra = _resolveAttrPairs(opts.additionalSignedAttributes, "a countersignature signed attribute value");
543
556
  extra.forEach(function (p) { if (p.type === O("contentType")) throw _err("cms/bad-input", "a countersignature must not carry a content-type attribute (RFC 5652 sec. 11.4)"); });
@@ -556,8 +569,9 @@ function _buildCountersignature(targetSigOctets, countersigner, opts) {
556
569
  });
557
570
  return intrinsic.chain(selfChecked, function () {
558
571
  var fields = [b.integer(BigInt(sidv.version)), sidv.sid, scheme.digestAlgId];
559
- if (attrs) fields.push(attrs.wire);
560
- fields.push(scheme.sigAlgId, b.octetString(sig));
572
+ if (attrs) _push(fields, attrs.wire);
573
+ _push(fields, scheme.sigAlgId);
574
+ _push(fields, b.octetString(sig));
561
575
  return { value: b.sequence(fields), certDer: certDer, digestAlgId: scheme.digestAlgId };
562
576
  });
563
577
  });
@@ -568,13 +582,17 @@ function _mergeCountersig(uaNode, newCsValues) {
568
582
  var CS = O("countersignature");
569
583
  var others = [], csValues = [];
570
584
  if (uaNode) uaNode.children.forEach(function (attr) {
571
- if (asn1.read.oid(attr.children[0]) === CS) attr.children[1].children.forEach(function (v) { csValues.push(v.bytes); });
572
- else others.push(attr.bytes);
585
+ if (asn1.read.oid(attr.children[0]) === CS) intrinsic.forEach(attr.children[1].children, function (v) { _push(csValues, v.bytes); });
586
+ else _push(others, attr.bytes);
573
587
  });
574
- newCsValues.forEach(function (v) { csValues.push(v); });
588
+ intrinsic.forEach(newCsValues, function (v) { _push(csValues, v); });
575
589
  var csAttr = b.sequence([b.oid(CS), b.set(csValues)]);
576
- var setOf = b.set(others.concat([csAttr]));
577
- var wire = Buffer.from(setOf); wire[0] = 0xA1;
590
+ /** @internal `concatList`, not `concat`: `Array.prototype.concat` builds its result through the
591
+ * species constructor, so a species answering with a Proxy intercepted the countersignature
592
+ * attribute as it was inserted and the merged value went out without it. `concatList` copies own
593
+ * indexes into an array it made itself. */
594
+ var setOf = b.set(intrinsic.concatList(others, [csAttr]));
595
+ var wire = intrinsic.bufferFrom(setOf); wire[0] = 0xA1;
578
596
  return wire;
579
597
  }
580
598
 
@@ -583,7 +601,7 @@ function _appendCountersigs(siNode, newCsValues) {
583
601
  var last = kids[kids.length - 1];
584
602
  var hasUa = last.tagClass === "context" && last.tagNumber === 1;
585
603
  var base = (hasUa ? kids.slice(0, kids.length - 1) : kids).map(function (k) { return k.bytes; });
586
- base.push(_mergeCountersig(hasUa ? last : null, newCsValues));
604
+ _push(base, _mergeCountersig(hasUa ? last : null, newCsValues));
587
605
  return b.sequence(base);
588
606
  }
589
607
 
@@ -603,7 +621,7 @@ function _spliceNested(siNode, j, newCsValues) {
603
621
  if (!found) throw _err("cms/bad-input", "the target signer carries no countersignature to countersign");
604
622
  var setOf = b.set(attrs); var wire = Buffer.from(setOf); wire[0] = 0xA1;
605
623
  var base = kids.slice(0, kids.length - 1).map(function (k) { return k.bytes; });
606
- base.push(wire);
624
+ _push(base, wire);
607
625
  return b.sequence(base);
608
626
  }
609
627
 
@@ -619,7 +637,11 @@ function _targetPreimage(siNode, opts) {
619
637
  var last = siNode.children[siNode.children.length - 1];
620
638
  var CS = O("countersignature");
621
639
  if (!last || last.tagClass !== "context" || last.tagNumber !== 1) throw _err("cms/bad-input", "the target signer carries no countersignature to countersign");
622
- var attr = last.children.filter(function (a) { return asn1.read.oid(a.children[0]) === CS; })[0];
640
+ /** @internal The selection returns the first matching attribute or null, because `filter(...)[0]`
641
+ * indexes a result that is EMPTY when the signer carries no countersignature attribute, and index
642
+ * 0 of an empty array answers from the array prototype: the refusal below would then not be
643
+ * reached and the signature bytes would be taken from whatever the accessor answered with. */
644
+ var attr = guard.list.firstMatch(last.children, function (a) { return asn1.read.oid(a.children[0]) === CS; });
623
645
  if (!attr) throw _err("cms/bad-input", "the target signer carries no countersignature to countersign");
624
646
  var values = attr.children[1].children;
625
647
  var j = opts.countersignatureOf;
@@ -653,15 +675,15 @@ function _countersign(cmsInput, signers, opts) {
653
675
  var jobs = [];
654
676
  targets.forEach(function (t) {
655
677
  var preimage = _targetPreimage(siSet.children[t], opts);
656
- list.forEach(function (cs) { jobs.push({ t: t, p: _buildCountersignature(preimage, cs, opts) }); });
678
+ intrinsic.forEach(list, function (cs) { _push(jobs, { t: t, p: _buildCountersignature(preimage, cs, opts) }); });
657
679
  });
658
680
  return intrinsic.chain(intrinsic.allOf(intrinsic.mapList(jobs, function (j) { return j.p; })), function (built) {
659
681
  var byTarget = intrinsic.create(null), certDers = [], csDigestAlgs = [];
660
682
  intrinsic.forEach(built, function (res, i) {
661
683
  var slot = byTarget[jobs[i].t] || (byTarget[jobs[i].t] = []);
662
- intrinsic.push(slot, res.value);
663
- intrinsic.push(certDers, res.certDer);
664
- intrinsic.push(csDigestAlgs, res.digestAlgId);
684
+ _push(slot, res.value);
685
+ _push(certDers, res.certDer);
686
+ _push(csDigestAlgs, res.digestAlgId);
665
687
  });
666
688
 
667
689
  var newSiSet = b.set(siSet.children.map(function (siNode, idx) {
@@ -675,8 +697,8 @@ function _countersign(cmsInput, signers, opts) {
675
697
  else if (sdKids[i].tagClass === "context" && sdKids[i].tagNumber === 1) crlsNode = sdKids[i];
676
698
  }
677
699
  var existing = [];
678
- if (certsNode) certsNode.children.forEach(function (c) { existing.push(c.bytes); });
679
- if (opts.certificates !== false) certDers.forEach(function (d) { existing.push(d); });
700
+ if (certsNode) intrinsic.forEach(certsNode.children, function (c) { _push(existing, c.bytes); });
701
+ if (opts.certificates !== false) intrinsic.forEach(certDers, function (d) { _push(existing, d); });
680
702
  /** @internal The DER SET ordering through the captured copy, sort AND comparator: read off its own
681
703
  * home, any of the three decides which certificate lands where in the set this message carries. */
682
704
  var allCerts = guard.list.sortedCopy(_dedupe(existing), intrinsic.compare);
@@ -693,20 +715,20 @@ function _countersign(cmsInput, signers, opts) {
693
715
  * comparison would list it a second time. */
694
716
  var listed = [];
695
717
  intrinsic.forEach(intrinsic.isArray(parsed.digestAlgorithms) ? parsed.digestAlgorithms : [],
696
- function (a) { intrinsic.push(listed, a); });
718
+ function (a) { _push(listed, a); });
697
719
  var digestAlgs = intrinsic.map(sdKids[1].children, function (d) { return d.bytes; });
698
720
  intrinsic.forEach(csDigestAlgs, function (der) {
699
721
  var info = _digestAlgIdentifier(der);
700
722
  var already = false;
701
723
  intrinsic.forEach(listed, function (alg) { if (cms.sameDigestAlgorithm(alg, info)) already = true; });
702
724
  if (already) return;
703
- intrinsic.push(listed, info);
704
- intrinsic.push(digestAlgs, der);
725
+ _push(listed, info);
726
+ _push(digestAlgs, der);
705
727
  });
706
728
  var newSdFields = [sdKids[0].bytes, b.set(digestAlgs), sdKids[2].bytes];
707
- if (allCerts.length) newSdFields.push(b.contextConstructed(0, Buffer.concat(allCerts)));
708
- if (crlsNode) newSdFields.push(crlsNode.bytes);
709
- newSdFields.push(newSiSet);
729
+ if (allCerts.length) _push(newSdFields, b.contextConstructed(0, intrinsic.bufferConcat(allCerts)));
730
+ if (crlsNode) _push(newSdFields, crlsNode.bytes);
731
+ _push(newSdFields, newSiSet);
710
732
  var newCi = b.sequence([root.children[0].bytes, b.explicit(0, b.sequence(newSdFields))]);
711
733
  return opts.pem ? pkix.pemEncode(newCi, "CMS", frameworkError.PemError) : newCi;
712
734
  });
@@ -732,7 +754,7 @@ function _appendUnsignedAttr(siNode, attrDer) {
732
754
  var existing = hasUa ? intrinsic.map(last.children, function (a) { return a.bytes; }) : [];
733
755
  var setOf = b.set(intrinsic.concat(existing, [attrDer]));
734
756
  var wire = intrinsic.bufferFrom(setOf); wire[0] = 0xA1;
735
- intrinsic.push(base, wire);
757
+ _push(base, wire);
736
758
  return b.sequence(base);
737
759
  }
738
760
 
@@ -955,7 +977,7 @@ function _attachTimestamp(input, token, opts) {
955
977
  }));
956
978
  var sdKids = t.sd.children;
957
979
  var newSdFields = intrinsic.map(intrinsic.arraySlice(sdKids, 0, sdKids.length - 1), function (k) { return k.bytes; });
958
- intrinsic.push(newSdFields, newSiSet);
980
+ _push(newSdFields, newSiSet);
959
981
  var out = b.sequence([t.root.children[0].bytes, b.explicit(0, b.sequence(newSdFields))]);
960
982
  return opts.pem ? pkix.pemEncode(out, "CMS", frameworkError.PemError) : out;
961
983
  }
package/lib/cms-verify.js CHANGED
@@ -203,7 +203,11 @@ function _preferBoundCandidate(si, candidates) {
203
203
  }
204
204
 
205
205
  function _certSki(cert) {
206
- var ext = (cert.extensions || []).filter(function (e) { return e.oid === oid.byName("subjectKeyIdentifier"); })[0];
206
+ /** @internal The selection returns the first matching row or null. `filter(...)[0]` indexes a
207
+ * result that is EMPTY when the extension is absent, and index 0 of an empty array answers from
208
+ * the array prototype, so a value installed there reads at the test below as an extension the
209
+ * certificate does not carry. */
210
+ var ext = guard.list.firstMatch(cert.extensions || [], function (e) { return e.oid === oid.byName("subjectKeyIdentifier"); });
207
211
  if (!ext) return null;
208
212
  try {
209
213
  return asn1.read.octetString(asn1.decode(ext.value));
@@ -359,7 +363,7 @@ async function _computeCountersigBytes(si, csTarget) {
359
363
  attrs = _decodeSignedAttrs(reTagged);
360
364
  } catch (e) { if (e instanceof CmsError) throw e; throw _err("cms/bad-signed-attrs", "the countersignature signedAttrs is not a valid SET OF Attribute", e); }
361
365
  if (intrinsic.filter(attrs, function (a) { return a.type === OID_CONTENT_TYPE; }).length) throw _err("cms/misplaced-attr", "a countersignature must not carry a content-type attribute (RFC 5652 sec. 11.4)");
362
- var mdAttr = intrinsic.filter(attrs, function (a) { return a.type === OID_MESSAGE_DIGEST; })[0];
366
+ var mdAttr = guard.list.firstMatch(attrs, function (a) { return a.type === OID_MESSAGE_DIGEST; });
363
367
  if (!mdAttr || mdAttr.values.length !== 1) throw _err("cms/bad-signed-attrs", "a countersignature's signedAttrs must carry exactly one message-digest attribute (RFC 5652 sec. 11.4)");
364
368
  var declared;
365
369
  try {
@@ -402,7 +406,7 @@ async function _computeSignedBytes(si, content, eContentType, digestByName) {
402
406
  ctOid = asn1.read.oid(ctAttr[0].values[0]);
403
407
  } catch (e) { throw _err("cms/bad-signed-attrs", "the content-type attribute value is not an OBJECT IDENTIFIER", e); }
404
408
  if (ctOid !== eContentType) return { mismatch: { code: "cms/content-type-mismatch", message: "the content-type signed attribute does not match the SignedData eContentType (RFC 5652 sec. 5.3)" } };
405
- var mdAttr = intrinsic.filter(attrs, function (a) { return a.type === OID_MESSAGE_DIGEST; })[0];
409
+ var mdAttr = guard.list.firstMatch(attrs, function (a) { return a.type === OID_MESSAGE_DIGEST; });
406
410
  if (!mdAttr || mdAttr.values.length !== 1) throw _err("cms/bad-signed-attrs", "signedAttrs must carry exactly one message-digest attribute (RFC 5652 sec. 5.4)");
407
411
  var declared;
408
412
  try {
@@ -1172,7 +1176,7 @@ var _permitsSigning = pkix.keyUsagePermits(pkix.makeNS("cms", CmsError, oid),
1172
1176
  ["digitalSignature", "contentCommitment", "nonRepudiation"]);
1173
1177
 
1174
1178
  function _keyUsagePermitsSigning(parsedCerts, der) {
1175
- var entry = intrinsic.filter(parsedCerts, function (c) { return intrinsic.bufferEquals(c.der, der); })[0];
1179
+ var entry = guard.list.firstMatch(parsedCerts, function (c) { return intrinsic.bufferEquals(c.der, der); });
1176
1180
  if (!entry) return true;
1177
1181
  return _permitsSigning(entry.cert);
1178
1182
  }
package/lib/crl-sign.js CHANGED
@@ -24,6 +24,9 @@ var x509Schema = require("./schema-x509");
24
24
  var signScheme = require("./sign-scheme");
25
25
  var guard = require("./guard-all");
26
26
  var intrinsic = require("./guard-intrinsic");
27
+ /** @internal The append every list here is built with: `push` stores at the index and a store
28
+ * consults a setter inherited there, and these lists become the bytes that get signed. */
29
+ var _push = intrinsic.append;
27
30
  var _hasOwn = intrinsic.hasOwn, _bufferEquals = intrinsic.bufferEquals;
28
31
  var _arrSlice = intrinsic.arraySlice, _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
29
32
  /** @internal The RECEIVER for the captured `Promise.resolve`, captured too. `resolve` builds through
@@ -184,11 +187,11 @@ function _idpValue(idp) {
184
187
  if (idp.fullName != null) {
185
188
  var entries = Array.isArray(idp.fullName) ? pkiBuild.reqDenseArray(idp.fullName, "issuingDistributionPoint.fullName", _err, "crl/bad-idp") : [idp.fullName];
186
189
  if (!entries.length) throw _err("crl/bad-idp", "issuingDistributionPoint fullName must carry at least one GeneralName");
187
- children.push(b.contextConstructed(0, b.contextConstructed(0, Buffer.concat(entries.map(_encodeGeneralName)))));
190
+ _push(children,b.contextConstructed(0, b.contextConstructed(0, Buffer.concat(entries.map(_encodeGeneralName)))));
188
191
  }
189
192
  var scopeTrue = 0;
190
- if (idp.onlyContainsUserCerts === true) { children.push(b.contextPrimitive(1, Buffer.from([0xff]))); scopeTrue++; }
191
- if (idp.onlyContainsCACerts === true) { children.push(b.contextPrimitive(2, Buffer.from([0xff]))); scopeTrue++; }
193
+ if (idp.onlyContainsUserCerts === true) { _push(children,b.contextPrimitive(1, Buffer.from([0xff]))); scopeTrue++; }
194
+ if (idp.onlyContainsCACerts === true) { _push(children,b.contextPrimitive(2, Buffer.from([0xff]))); scopeTrue++; }
192
195
  if (idp.indirectCRL === true) throw _err("crl/bad-idp", _INDIRECT_IDP_DEFERRED);
193
196
  if (scopeTrue > 1) throw _err("crl/bad-idp", "at most one of onlyContainsUserCerts / onlyContainsCACerts may be TRUE (RFC 5280 sec. 5.2.5)");
194
197
  if (!children.length) throw _err("crl/bad-idp", "issuingDistributionPoint MUST NOT be empty (RFC 5280 sec. 5.2.5)");
@@ -232,7 +235,7 @@ function _buildCrlExtensions(spec, ctx) {
232
235
  var id = O(oidName);
233
236
  if (seen[id]) throw _err("crl/bad-input", "duplicate CRL extension " + oidName + " (RFC 5280 sec. 5.2 -- at most one instance)");
234
237
  seen[id] = true;
235
- out.push(_ext(id, critical, valueDer));
238
+ _push(out,_ext(id, critical, valueDer));
236
239
  }
237
240
  var crlNumberVal = null;
238
241
  if (spec.crlNumber != null) { var cn = _boundedInteger(spec.crlNumber, "cRLNumber"); crlNumberVal = cn.value; push("cRLNumber", false, cn.tlv); }
@@ -264,7 +267,7 @@ function _buildCrlExtensions(spec, ctx) {
264
267
  }
265
268
  _assertExtensionValueDecodes(node, extnId, "extension");
266
269
  if (extnId === O("deltaCRLIndicator")) isDelta = true;
267
- out.push(b.raw(der));
270
+ _push(out,b.raw(der));
268
271
  });
269
272
  if (isDelta) {
270
273
  if (seen[O("freshestCRL")]) throw _err("crl/bad-input", "freshestCRL MUST NOT appear in a delta CRL (RFC 5280 sec. 5.2.6)");
@@ -323,7 +326,7 @@ function _buildRevoked(entryList, isDelta) {
323
326
  var id = O(oidName);
324
327
  if (seen[id]) throw _err("crl/bad-input", "duplicate entry extension " + oidName + " in revoked entry [" + idx + "]");
325
328
  seen[id] = true;
326
- entryExts.push(_ext(id, critical, valueDer));
329
+ _push(entryExts,_ext(id, critical, valueDer));
327
330
  }
328
331
  if (e.reason != null) {
329
332
  var codeNum = _resolveReason(e.reason, isDelta);
@@ -360,10 +363,10 @@ function _buildRevoked(entryList, isDelta) {
360
363
  }
361
364
  }
362
365
  _assertExtensionValueDecodes(xnode, extnId, "entry extension");
363
- entryExts.push(b.raw(der));
366
+ _push(entryExts,b.raw(der));
364
367
  });
365
368
  }
366
- if (entryExts.length) { anyExt = true; children.push(b.sequence(entryExts)); }
369
+ if (entryExts.length) { anyExt = true; _push(children,b.sequence(entryExts)); }
367
370
  return b.sequence(children);
368
371
  });
369
372
  return { entries: entries, anyExt: anyExt };
@@ -375,7 +378,11 @@ function _parseIssuerCert(cert) {
375
378
  }
376
379
 
377
380
  function _assertIssuerCanSignCrl(issuerCert) {
378
- var kuExt = (issuerCert.extensions || []).filter(function (e) { return e.oid === O("keyUsage"); })[0];
381
+ /** @internal The selection returns the first matching row or null. `filter(...)[0]` indexes a
382
+ * result that is EMPTY when the certificate carries no keyUsage, and index 0 of an empty array
383
+ * answers from the array prototype, so a value installed there would be decoded as the issuer's
384
+ * key usage and decide whether it may sign this CRL. */
385
+ var kuExt = guard.list.firstMatch(issuerCert.extensions || [], function (e) { return e.oid === O("keyUsage"); });
379
386
  if (!kuExt) return;
380
387
  var ku;
381
388
  try { ku = EXT_DECODERS[O("keyUsage")](kuExt.value); }
@@ -453,13 +460,13 @@ function _sign(spec, issuer, opts) {
453
460
  * into the PreTBSCertList the alternative signature covers. */
454
461
  function tbsOver(extList, omitSignatureAlg) {
455
462
  var tbsChildren = [];
456
- if (version === 2) tbsChildren.push(b.integer(1n));
457
- if (omitSignatureAlg !== true) tbsChildren.push(scheme.sigAlgId);
458
- tbsChildren.push(issuerDer);
459
- tbsChildren.push(thisU);
460
- if (nextU) tbsChildren.push(nextU);
461
- if (revoked.entries.length) tbsChildren.push(b.sequence(revoked.entries));
462
- if (extList.length) tbsChildren.push(b.explicit(0, b.sequence(extList)));
463
+ if (version === 2) _push(tbsChildren,b.integer(1n));
464
+ if (omitSignatureAlg !== true) _push(tbsChildren,scheme.sigAlgId);
465
+ _push(tbsChildren,issuerDer);
466
+ _push(tbsChildren,thisU);
467
+ if (nextU) _push(tbsChildren,nextU);
468
+ if (revoked.entries.length) _push(tbsChildren,b.sequence(revoked.entries));
469
+ if (extList.length) _push(tbsChildren,b.explicit(0, b.sequence(extList)));
463
470
  return b.sequence(tbsChildren);
464
471
  }
465
472
 
@@ -813,7 +820,7 @@ function isRevoked(crl, serialNumber, opts) {
813
820
 
814
821
  function _findExtOid(list, name) {
815
822
  var want = O(name);
816
- return (list || []).filter(function (e) { return e.oid === want; })[0] || null;
823
+ return guard.list.firstMatch(list || [], function (e) { return e.oid === want; });
817
824
  }
818
825
 
819
826
  var _IDP_SCHEMA = pkix.issuingDistributionPoint("crl/scope-not-authoritative");
package/lib/csr-sign.js CHANGED
@@ -26,6 +26,9 @@ var pkiBuild = require("./pki-build");
26
26
  var frameworkError = require("./framework-error");
27
27
  var guard = require("./guard-all");
28
28
  var intrinsic = require("./guard-intrinsic");
29
+ /** @internal The append every list here is built with: `push` stores at the index and a store
30
+ * consults a setter inherited there, and these lists become the bytes that get signed. */
31
+ var _push = intrinsic.append;
29
32
  /** @internal The promise a self-check is awaited through, built from the constructor captured at load.
30
33
  * `Promise.resolve` builds from its RECEIVER, so reading the global binding at the call hands the
31
34
  * construction to whatever that binding holds, and a constructor settling without awaiting its
@@ -224,7 +227,7 @@ function _sign(spec, key, opts) {
224
227
  function addAttr(attrType, valueTlv) {
225
228
  if (seenAttr[attrType]) throw _err("csr/bad-input", "duplicate " + (oid.name(attrType) || attrType) + " attribute");
226
229
  seenAttr[attrType] = true;
227
- attrs.push(b.sequence([b.oid(attrType), b.set([valueTlv])]));
230
+ _push(attrs,b.sequence([b.oid(attrType), b.set([valueTlv])]));
228
231
  }
229
232
  if (spec.extensionRequest != null) addAttr(O("extensionRequest"), _buildRequestedExtensions(spec.extensionRequest, subjectSpki));
230
233
  if (spec.challengePassword != null) addAttr(O("challengePassword"), _challengePassword(spec.challengePassword));
@@ -259,7 +262,7 @@ function _sign(spec, key, opts) {
259
262
  if (!n.children[1].children || n.children[1].children.length === 0) throw _err("csr/bad-input", "pre-encoded attribute [" + i + "] value SET must contain at least one value (RFC 2986 SET SIZE(1..MAX))");
260
263
  if (seenAttr[at]) throw _err("csr/bad-input", "duplicate " + (oid.name(at) || at) + " attribute");
261
264
  seenAttr[at] = true;
262
- attrs.push(b.raw(der));
265
+ _push(attrs,b.raw(der));
263
266
  });
264
267
  }
265
268
 
package/lib/ct.js CHANGED
@@ -64,6 +64,7 @@ var _bufferCompare = intrinsic.compare;
64
64
  var _subarray = intrinsic.subarray;
65
65
  var _toLowerCase = intrinsic.toLowerCase;
66
66
  var _ctTrim = intrinsic.uncurry(String.prototype.trim);
67
+ var _writeBigUInt64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
67
68
  var _bufCopy = intrinsic.uncurry(Buffer.prototype.copy);
68
69
  var _writeU64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
69
70
  var _searchSet = intrinsic.uncurry(URLSearchParams.prototype.set);
@@ -293,8 +294,11 @@ function parseSctList(extValue) {
293
294
  }
294
295
  sctCount.tick();
295
296
  var one = _parseSct(outer.subReader(sctLen, "ct/list-trailing-bytes"), sctLen);
296
- if (one.unknown) { var u = { version: one.version, rawSct: one.rawSct }; unknownScts.push(u); all.push(u); }
297
- else { scts.push(one); all.push(one); }
297
+ /** @internal The parsed timestamps are appended by defining their indexes: the lists a caller
298
+ * reads its verdict from, and the `all` list a policy counts, are what a numeric setter on the
299
+ * array prototype would otherwise take an entry out of. */
300
+ if (one.unknown) { var u = { version: one.version, rawSct: one.rawSct }; intrinsic.append(unknownScts, u); intrinsic.append(all, u); }
301
+ else { intrinsic.append(scts, one); intrinsic.append(all, one); }
298
302
  }
299
303
  return guard.verdict.of({ scts: scts, unknownScts: unknownScts, all: all });
300
304
  }
@@ -366,29 +370,36 @@ function reconstructSignedData(entry, sct) {
366
370
  throw new CtError("ct/bad-input", "reconstructSignedData expects a decoded v1 SCT from parseSctList().scts[]");
367
371
  }
368
372
  var tsVal = guard.range.uint64(sct.timestamp, _ctErr, "ct/bad-input", "sct.timestamp (RFC 6962 3.2)");
373
+ /** @internal EVERY component of this preimage is appended by defining its index, and the
374
+ * concatenation is the captured one. These bytes are what a log's signature is verified over, so a
375
+ * numeric setter inherited from the array prototype replacing any one of them, the version, the
376
+ * signature type, the timestamp, the entry type, the certificate or the extensions, puts the
377
+ * verification on bytes the log never signed. Converting only the timestamp left the rest open,
378
+ * which is the whole class: the rule belongs to the function, not to the line it was found on. */
369
379
  var parts = [];
370
- parts.push(_bufferFrom([sct.version & 0xff]));
371
- parts.push(_bufferFrom([0]));
372
- var ts = _bufferAlloc(8); ts.writeBigUInt64BE(tsVal); parts.push(ts);
373
- parts.push(_bufferFrom([(entryType >> 8) & 0xff, entryType & 0xff]));
380
+ intrinsic.append(parts, _bufferFrom([sct.version & 0xff]));
381
+ intrinsic.append(parts, _bufferFrom([0]));
382
+ var ts = _bufferAlloc(8); _writeBigUInt64BE(ts, tsVal); intrinsic.append(parts, ts);
383
+ intrinsic.append(parts, _bufferFrom([(entryType >> 8) & 0xff, entryType & 0xff]));
374
384
  if (entryType === 0) {
375
385
  var cert = _toBuffer(entry.leafCert, "leafCert", undefined, undefined, 0xffffff, "ct/bad-tbs-length");
376
- parts.push(_u24Bytes(cert.length)); parts.push(cert);
386
+ intrinsic.append(parts, _u24Bytes(cert.length)); intrinsic.append(parts, cert);
377
387
  } else {
378
388
  var ikh = _toBuffer(entry.issuerKeyHash, "issuerKeyHash");
379
389
  if (ikh.length !== 32) {
380
390
  throw new CtError("ct/bad-issuer-key-hash", "issuer_key_hash must be exactly 32 bytes (SHA-256 of the issuer SPKI), got " + ikh.length + " (RFC 6962 sec. 3.2)");
381
391
  }
382
392
  var tbs = _toBuffer(entry.tbsCertificate, "tbsCertificate", undefined, undefined, 0xffffff, "ct/bad-tbs-length");
383
- parts.push(ikh);
384
- parts.push(_u24Bytes(tbs.length)); parts.push(tbs);
393
+ intrinsic.append(parts, ikh);
394
+ intrinsic.append(parts, _u24Bytes(tbs.length)); intrinsic.append(parts, tbs);
385
395
  }
386
396
  var ext = _toBuffer(sct.extensions, "sct.extensions", undefined, undefined, 0xffff, "ct/bad-extensions");
387
397
  if (ext.length > 0xffff) {
388
398
  throw new CtError("ct/bad-extensions", "CtExtensions must be 0..65535 bytes, got " + ext.length + " (RFC 6962 3.2)");
389
399
  }
390
- parts.push(_bufferFrom([(ext.length >> 8) & 0xff, ext.length & 0xff])); parts.push(ext);
391
- return Buffer.concat(parts);
400
+ intrinsic.append(parts, _bufferFrom([(ext.length >> 8) & 0xff, ext.length & 0xff]));
401
+ intrinsic.append(parts, ext);
402
+ return intrinsic.bufferConcat(parts);
392
403
  }
393
404
 
394
405
  var CT_HASH = intrinsic.assign(intrinsic.create(null), { sha256: "SHA-256" });
@@ -584,7 +595,7 @@ function encodeSctList(scts) {
584
595
  var el = ew.build();
585
596
  total += el.length;
586
597
  if (total > 0xffff) throw new CtError("ct/too-large", "the SCT list body exceeds the 65535-byte maximum (RFC 6962 sec. 3.3)");
587
- elements.push(el);
598
+ intrinsic.append(elements, el);
588
599
  }
589
600
  var lw = new TlsWriter();
590
601
  lw.vector(2, 1, 0xffff, Buffer.concat(elements, total), "ct/too-large");
@@ -803,7 +814,7 @@ function parseLogList(json, opts) {
803
814
  continue;
804
815
  }
805
816
  byLogId[rec.logIdHex] = rec;
806
- logs.push(rec);
817
+ intrinsic.append(logs, rec);
807
818
  }
808
819
  }
809
820
  }
@@ -1092,13 +1103,13 @@ function x509CertEntry(cert, issuer) {
1092
1103
  for (var j = 0; j < extsSeq.children.length; j++) {
1093
1104
  var ext = extsSeq.children[j];
1094
1105
  if (ext.children[0] && intrinsic.bufferEquals(ext.children[0].bytes, sctOid)) { removed++; continue; }
1095
- intrinsic.push(kept, ext.bytes);
1106
+ intrinsic.append(kept, ext.bytes);
1096
1107
  }
1097
1108
  if (removed === 0) throw _ctErr("ct/no-sct-extension", "the certificate carries no signedCertificateTimestampList extension (RFC 6962 sec. 3.2)");
1098
1109
  var tbsChildren = [];
1099
1110
  for (var k = 0; k < tbs.children.length; k++) {
1100
- if (k !== wrapIdx) { intrinsic.push(tbsChildren, tbs.children[k].bytes); continue; }
1101
- if (kept.length > 0) intrinsic.push(tbsChildren, asn1.build.explicit(3, asn1.build.sequence(kept)));
1111
+ if (k !== wrapIdx) { intrinsic.append(tbsChildren, tbs.children[k].bytes); continue; }
1112
+ if (kept.length > 0) intrinsic.append(tbsChildren, asn1.build.explicit(3, asn1.build.sequence(kept)));
1102
1113
  }
1103
1114
  var issuerKeyHash = nodeCrypto.createHash("sha256").update(issSpki).digest();
1104
1115
  return { entryType: 1, tbsCertificate: asn1.build.sequence(tbsChildren), issuerKeyHash: issuerKeyHash };