@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
package/lib/cbor-det.js CHANGED
@@ -40,6 +40,12 @@ var constants = require("./constants");
40
40
  var frameworkError = require("./framework-error");
41
41
  var asn1 = require("./asn1-der");
42
42
  var guard = require("./guard-all");
43
+ /** @internal The append every list in this module is built with. `push` STORES at the index, and a
44
+ * store walks the prototype chain for a setter, so an accessor inherited at an array index receives
45
+ * each element as it is appended and the index then reads back whatever its getter answers. The
46
+ * decoded children below are what every C509 field is read out of, so a replaced element there is a
47
+ * field this codec never decoded. */
48
+ var _push = guard.list.append;
43
49
 
44
50
  var CborError = frameworkError.CborError;
45
51
 
@@ -141,7 +147,7 @@ function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
141
147
  var cp = contentStart;
142
148
  for (var i = 0n; i < argument; i++) {
143
149
  var el = _decodeItem(buf, cp, limit, depth + 1, maxD, rules, state);
144
- children.push(el.node);
150
+ _push(children, el.node);
145
151
  cp = el.end;
146
152
  }
147
153
  end = cp;
@@ -158,7 +164,7 @@ function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
158
164
  if (cmp > 0) throw new CborError("cbor/unsorted-map-keys", "map keys are not in bytewise-ascending order");
159
165
  if (cmp === 0) throw new CborError("cbor/duplicate-map-key", "duplicate map key");
160
166
  }
161
- children.push([k.node, v.node]);
167
+ _push(children, [k.node, v.node]);
162
168
  }
163
169
  end = mp;
164
170
  } else if (mt === 6) {
@@ -682,7 +688,7 @@ var build = Object.assign(Object.create(null), {
682
688
  enc = guard.list.sortedCopy(enc, function (a, b) { return guard.bytes.compare(a[0], b[0]); });
683
689
  for (var i = 1; i < enc.length; i++) { if (guard.bytes.compare(enc[i - 1][0], enc[i][0]) === 0) throw new CborError("cbor/duplicate-map-key", "build.map: duplicate map key"); }
684
690
  var flat = [_head(5, pairs.length, "build.map")];
685
- enc.forEach(function (p) { flat.push(p[0], p[1]); });
691
+ enc.forEach(function (p) { _push(flat, p[0]); _push(flat, p[1]); });
686
692
  return _assertDecodes(Buffer.concat(flat), "build.map");
687
693
  },
688
694
  tag: function (tagNum, inner) { return _assertDecodes(Buffer.concat([_head(6, tagNum, "build.tag"), _cbItem(inner, "build.tag content")]), "build.tag"); },
package/lib/cmc-build.js CHANGED
@@ -22,6 +22,9 @@ var key = require("./key");
22
22
  var _createPublicKey = nodeCrypto.createPublicKey;
23
23
  var guard = require("./guard-all");
24
24
  var intrinsic = require("./guard-intrinsic");
25
+ /** @internal The append every list here is built with: `push` stores at the index and a store
26
+ * consults a setter inherited there, and these lists become the controls a request carries. */
27
+ var _push = intrinsic.append;
25
28
  var _hasOwn = intrinsic.hasOwn;
26
29
  var _isArray = intrinsic.isArray;
27
30
  var _isBuffer = intrinsic.isBuffer;
@@ -449,7 +452,7 @@ function _assertSecret(secret, what) {
449
452
  }
450
453
 
451
454
  function _ownSecret(buf, owned) {
452
- owned.push(buf);
455
+ _push(owned,buf);
453
456
  return buf;
454
457
  }
455
458
 
@@ -467,8 +470,8 @@ function identityProofV2(secret, reqSequenceBytes, identity) {
467
470
  _ownSecret(Buffer.from(identity, "utf8"), owned),
468
471
  ]), owned);
469
472
  }
470
- key = nodeCrypto.createHash("sha256").update(material).digest();
471
- var witness = nodeCrypto.createHmac("sha256", key).update(reqSequenceBytes).digest();
473
+ key = guard.crypto.digest("sha256", material);
474
+ var witness = guard.crypto.hmac("sha256", key, reqSequenceBytes);
472
475
  return b.sequence([algId(OID_SHA256), algId(OID_HMAC_SHA256), b.octetString(witness)]);
473
476
  } finally {
474
477
  if (key) guard.secret.zeroize(key, CmcError, "cmc/bad-input", "the Identity Proof MAC key");
@@ -538,7 +541,7 @@ function _provesRequestKey(opening, outgoing) {
538
541
  /** @internal Keys of different types are never the same key, and comparing them through the
539
542
  * runtime's equality leaves a fault queued in the crypto library that surfaces on the next
540
543
  * unrelated key import in the process, so the type decides that case first. */
541
- if (requested.asymmetricKeyType !== opening.key.asymmetricKeyType) return false;
544
+ if (guard.crypto.keyType(requested) !== guard.crypto.keyType(opening.key)) return false;
542
545
  return intrinsic.keyEquals(requested, opening.key);
543
546
  }
544
547
  /** @internal A key the runtime engine cannot read has no KeyObject to compare, and a composite
@@ -604,7 +607,7 @@ async function _recoverProofValue(decoded, recipient, witnessHash) {
604
607
  continue; // allow:swallow-unverified this recipient is not addressed to the supplied key; the witness decides
605
608
  }
606
609
  var candidate = opened.content;
607
- var computed = nodeCrypto.createHash(witnessHash).update(candidate).digest();
610
+ var computed = guard.crypto.digest(witnessHash, candidate);
608
611
  var matches = computed.length === decoded.witness.length &&
609
612
  guard.crypto.constantTimeEqual(computed, decoded.witness);
610
613
  guard.secret.zeroize(computed, CmcError, "cmc/bad-input", "the computed witness");
@@ -671,7 +674,7 @@ async function answerPopChallenge(popChallenge, ids) {
671
674
  * in the challenge at all: neither side re-encodes it. */
672
675
  macKey = _bufferFrom(proofValue.length > POP_MAC_KEY_MAX_BYTES
673
676
  ? _subarray(proofValue, 0, POP_MAC_KEY_MAX_BYTES) : proofValue);
674
- var thePOP = nodeCrypto.createHmac(macHash, macKey).update(decoded.requestBytes).digest();
677
+ var thePOP = guard.crypto.hmac(macHash, macKey, decoded.requestBytes);
675
678
  return { algBytes: decoded.thePOPAlgID.bytes, thePOP: thePOP, ids: ids,
676
679
  recipientSpki: await _openingPublicKey(recipient, recovered.recipientType),
677
680
  challengedRequest: _requestIdentity(decoded.request) };
@@ -685,13 +688,18 @@ async function answerPopChallenge(popChallenge, ids) {
685
688
 
686
689
  function popLinkWitnessV2(secret, R) {
687
690
  _assertSecret(secret, "a POP Link Witness V2 control");
688
- var key = nodeCrypto.createHash("sha256").update(secret, "utf8").digest();
691
+ /** @internal The secret's octets, held so the finally can wipe them. Handing the string and an
692
+ * encoding to a digest instead leaves the copy inside the provider, where nothing clears it. */
693
+ var material = _bufferFrom(secret, "utf8");
694
+ var key = null;
689
695
  try {
696
+ key = guard.crypto.digest("sha256", material);
690
697
  /** @internal Inside the try, so a MAC that faults on its message still wipes the key above it. */
691
- var witness = nodeCrypto.createHmac("sha256", key).update(R).digest();
698
+ var witness = guard.crypto.hmac("sha256", key, R);
692
699
  return b.sequence([algId(OID_SHA256), algId(OID_HMAC_SHA256), b.octetString(witness)]);
693
700
  } finally {
694
- guard.secret.zeroize(key, CmcError, "cmc/bad-input", "the POP Link MAC key");
701
+ guard.secret.zeroize(material, CmcError, "cmc/bad-input", "the POP Link secret");
702
+ if (key !== null) guard.secret.zeroize(key, CmcError, "cmc/bad-input", "the POP Link MAC key");
695
703
  }
696
704
  }
697
705
 
@@ -804,15 +812,15 @@ async function _build(spec, signer, opts) {
804
812
 
805
813
  _assertNoDuplicateBinding(callerControls, spec);
806
814
  if (spec.transactionId != null) {
807
- controls.push(encodeControl(OID_TRANSACTION_ID,
815
+ _push(controls,encodeControl(OID_TRANSACTION_ID,
808
816
  [b.integer(_asBigInt(spec.transactionId, "spec.transactionId"))], ids));
809
817
  }
810
818
  if (spec.senderNonce != null) {
811
- controls.push(encodeControl(OID_SENDER_NONCE,
819
+ _push(controls,encodeControl(OID_SENDER_NONCE,
812
820
  [b.octetString(_der(spec.senderNonce, "spec.senderNonce"))], ids));
813
821
  }
814
822
  if (spec.dataReturn != null) {
815
- controls.push(encodeControl(OID_DATA_RETURN,
823
+ _push(controls,encodeControl(OID_DATA_RETURN,
816
824
  [b.octetString(_der(spec.dataReturn, "spec.dataReturn"))], ids));
817
825
  }
818
826
 
@@ -839,8 +847,8 @@ async function _build(spec, signer, opts) {
839
847
  if (identity != null && typeof identity !== "string") {
840
848
  throw E("cmc/bad-input", "identityProof.identity is the UTF8String the Identification control carries");
841
849
  }
842
- if (identity != null) controls.push(encodeControl(OID_IDENTIFICATION, [b.utf8(identity)], ids));
843
- controls.push(encodeControl(OID_IDENTITY_PROOF_V2,
850
+ if (identity != null) _push(controls,encodeControl(OID_IDENTIFICATION, [b.utf8(identity)], ids));
851
+ _push(controls,encodeControl(OID_IDENTITY_PROOF_V2,
844
852
  [identityProofV2(spec.identityProof.secret, reqSequenceBytes, carriedIdentity)], ids));
845
853
  }
846
854
 
@@ -932,9 +940,9 @@ async function _build(spec, signer, opts) {
932
940
  if (typeof rBytes !== "number" || !Number.isInteger(rBytes) || rBytes < 1) {
933
941
  throw E("cmc/bad-input", "popLinkRandomBytes must be a positive integer");
934
942
  }
935
- var R = nodeCrypto.randomBytes(rBytes);
936
- controls.push(encodeControl(OID_POP_LINK_RANDOM, [b.octetString(R)], ids));
937
- controls.push(encodeControl(O("id-cmc-popLinkWitnessV2"),
943
+ var R = guard.crypto.randomBytes(rBytes);
944
+ _push(controls,encodeControl(OID_POP_LINK_RANDOM, [b.octetString(R)], ids));
945
+ _push(controls,encodeControl(O("id-cmc-popLinkWitnessV2"),
938
946
  [popLinkWitnessV2(spec.popLink.secret, R)], ids));
939
947
  }
940
948
 
@@ -1016,7 +1024,7 @@ function _copySigners(signer, owned) {
1016
1024
  return c;
1017
1025
  }
1018
1026
  function _own(buf, isSecret) {
1019
- if (isSecret && owned) owned.push(buf);
1027
+ if (isSecret && owned) _push(owned,buf);
1020
1028
  return buf;
1021
1029
  }
1022
1030
  return Array.isArray(signer) ? guard.list.copyMap(signer, one) : one(signer);
package/lib/cmp-build.js CHANGED
@@ -56,7 +56,9 @@ var _bufferConcat = intrinsic.bufferConcat;
56
56
  var _map = intrinsic.map;
57
57
  var _keys = intrinsic.keys;
58
58
  var _forEach = intrinsic.forEach;
59
- var _push = intrinsic.push;
59
+ /** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
60
+ * setter, so an accessor there takes the element being appended. `append` defines it. */
61
+ var _push = intrinsic.append;
60
62
  var _stringify = intrinsic.stringify;
61
63
  var _bigInt = intrinsic.BigInt;
62
64
  var _Date = intrinsic.Date;
@@ -167,7 +169,7 @@ function _encodeInfoTypeAndValue(itav) {
167
169
  if (typeof itav.infoType !== "string" || O(itav.infoType) == null) throw _err("cmp/bad-name", "unknown infoType " + guard.text.showValue(itav.infoType));
168
170
  var children = [b.oid(O(itav.infoType))];
169
171
  var val = _encodeInfoValue(itav);
170
- if (val != null) children.push(val);
172
+ if (val != null) _push(children,val);
171
173
  return b.sequence(children);
172
174
  }
173
175
 
@@ -238,16 +240,16 @@ function _encodeHeader(headerSpec, protectionAlgDer, pvno) {
238
240
  ];
239
241
  if (headerSpec.messageTime != null) {
240
242
  guard.time.assertEncodable(headerSpec.messageTime, _err, "cmp/bad-input", "header.messageTime");
241
- children.push(b.explicit(0, b.generalizedTime(headerSpec.messageTime)));
243
+ _push(children,b.explicit(0, b.generalizedTime(headerSpec.messageTime)));
242
244
  }
243
- if (protectionAlgDer != null) children.push(b.explicit(1, b.raw(protectionAlgDer)));
244
- if (headerSpec.senderKID != null) children.push(b.explicit(2, _reqOctets(headerSpec.senderKID, "header.senderKID")));
245
- if (headerSpec.recipKID != null) children.push(b.explicit(3, _reqOctets(headerSpec.recipKID, "header.recipKID")));
246
- if (headerSpec.transactionID != null) children.push(b.explicit(4, _reqOctets(headerSpec.transactionID, "header.transactionID")));
247
- if (headerSpec.senderNonce != null) children.push(b.explicit(5, _reqOctets(headerSpec.senderNonce, "header.senderNonce")));
248
- if (headerSpec.recipNonce != null) children.push(b.explicit(6, _reqOctets(headerSpec.recipNonce, "header.recipNonce")));
249
- if (headerSpec.freeText != null) children.push(b.explicit(7, _encodePkiFreeText(headerSpec.freeText, "cmp/bad-freetext", "header.freeText")));
250
- if (headerSpec.generalInfo != null) children.push(b.explicit(8, _encodeGeneralInfo(headerSpec.generalInfo, "cmp/bad-general-info", "header.generalInfo")));
245
+ if (protectionAlgDer != null) _push(children,b.explicit(1, b.raw(protectionAlgDer)));
246
+ if (headerSpec.senderKID != null) _push(children,b.explicit(2, _reqOctets(headerSpec.senderKID, "header.senderKID")));
247
+ if (headerSpec.recipKID != null) _push(children,b.explicit(3, _reqOctets(headerSpec.recipKID, "header.recipKID")));
248
+ if (headerSpec.transactionID != null) _push(children,b.explicit(4, _reqOctets(headerSpec.transactionID, "header.transactionID")));
249
+ if (headerSpec.senderNonce != null) _push(children,b.explicit(5, _reqOctets(headerSpec.senderNonce, "header.senderNonce")));
250
+ if (headerSpec.recipNonce != null) _push(children,b.explicit(6, _reqOctets(headerSpec.recipNonce, "header.recipNonce")));
251
+ if (headerSpec.freeText != null) _push(children,b.explicit(7, _encodePkiFreeText(headerSpec.freeText, "cmp/bad-freetext", "header.freeText")));
252
+ if (headerSpec.generalInfo != null) _push(children,b.explicit(8, _encodeGeneralInfo(headerSpec.generalInfo, "cmp/bad-general-info", "header.generalInfo")));
251
253
  return b.sequence(children);
252
254
  }
253
255
 
@@ -267,8 +269,8 @@ function _encodePkiStatusInfo(si, code) {
267
269
  if (!si || typeof si !== "object" || Buffer.isBuffer(si)) throw _err(code, "a PKIStatusInfo must be an object { status, statusString?, failInfo? }");
268
270
  if (typeof si.status !== "number" || !Number.isInteger(si.status) || si.status < 0 || si.status > 6) throw _err(code, "statusInfo.status must be a PKIStatus 0..6 (RFC 9810 sec. 5.2.3)");
269
271
  var children = [b.integer(BigInt(si.status))];
270
- if (si.statusString != null) children.push(_encodePkiFreeText(si.statusString, code, "statusInfo.statusString"));
271
- if (si.failInfo != null) children.push(_encodeFailInfo(si.failInfo, code));
272
+ if (si.statusString != null) _push(children,_encodePkiFreeText(si.statusString, code, "statusInfo.statusString"));
273
+ if (si.failInfo != null) _push(children,_encodeFailInfo(si.failInfo, code));
272
274
  return b.sequence(children);
273
275
  }
274
276
 
@@ -278,10 +280,10 @@ function _encodeCertStatus(cs, state) {
278
280
  _reqOctets(cs.certHash, "certConf certHash"),
279
281
  b.integer(_reqIdInt(cs.certReqId, "cmp/bad-cert-status", "CertStatus certReqId")),
280
282
  ];
281
- if (cs.statusInfo != null) children.push(_encodePkiStatusInfo(cs.statusInfo, "cmp/bad-cert-status"));
283
+ if (cs.statusInfo != null) _push(children,_encodePkiStatusInfo(cs.statusInfo, "cmp/bad-cert-status"));
282
284
  if (cs.hashAlg != null) {
283
285
  if (typeof cs.hashAlg !== "string" || !CERT_CONF_HASH_ALGS[cs.hashAlg]) throw _err("cmp/bad-name", "certConf hashAlg must be a hash algorithm (sha256 / sha384 / sha512 / sha3-256 / sha3-512 / sha1); got " + guard.text.showValue(cs.hashAlg));
284
- children.push(b.explicit(0, _algIdNoParams(cs.hashAlg)));
286
+ _push(children,b.explicit(0, _algIdNoParams(cs.hashAlg)));
285
287
  state.usesCmp2021 = true;
286
288
  }
287
289
  return b.sequence(children);
@@ -317,7 +319,7 @@ function _encodeRevDetails(rd) {
317
319
  certDetails = b.raw(crmf.buildCertTemplate(rd.certDetails));
318
320
  }
319
321
  var children = [certDetails];
320
- if (rd.crlEntryDetails != null) children.push(b.raw(_encodeCrlEntryDetails(rd.crlEntryDetails)));
322
+ if (rd.crlEntryDetails != null) _push(children,b.raw(_encodeCrlEntryDetails(rd.crlEntryDetails)));
321
323
  return b.sequence(children);
322
324
  }
323
325
 
@@ -419,12 +421,12 @@ function _encodeCertifiedKeyPair(ckp, state) {
419
421
  var children = [_encodeCertOrEncCert(ckp, state)];
420
422
  if (ckp.privateKey != null) {
421
423
  var pk = _b.reqDer(ckp.privateKey, "certifiedKeyPair.privateKey (a pre-encoded EncryptedKey DER)");
422
- children.push(b.explicit(0, b.raw(pk)));
424
+ _push(children,b.explicit(0, b.raw(pk)));
423
425
  var pkNode;
424
426
  try { pkNode = asn1.decode(pk); } catch (e) { throw _err("cmp/bad-cert-response", "certifiedKeyPair.privateKey is not valid DER", e); }
425
427
  if (pkNode.tagClass === "context" && pkNode.tagNumber === 0) state.usesCmp2021 = true;
426
428
  }
427
- if (ckp.publicationInfo != null) children.push(b.explicit(1, b.raw(_b.reqDer(ckp.publicationInfo, "certifiedKeyPair.publicationInfo (a pre-encoded DER)"))));
429
+ if (ckp.publicationInfo != null) _push(children,b.explicit(1, b.raw(_b.reqDer(ckp.publicationInfo, "certifiedKeyPair.publicationInfo (a pre-encoded DER)"))));
428
430
  return b.sequence(children);
429
431
  }
430
432
 
@@ -435,8 +437,8 @@ function _encodeCertResponse(cr, state) {
435
437
  if (hasCkp && cr.status.failInfo != null) throw _err("cmp/bad-cert-response", "a CertResponse must not carry both failInfo and certifiedKeyPair");
436
438
  if (hasCkp && cr.status.status !== 0 && cr.status.status !== 1) throw _err("cmp/bad-cert-response", "a CertResponse certifiedKeyPair is allowed only under a granting status (accepted / grantedWithMods)");
437
439
  var children = [b.integer(_reqIdInt(cr.certReqId, "cmp/bad-cert-response", "CertResponse certReqId")), _encodePkiStatusInfo(cr.status, "cmp/bad-cert-response")];
438
- if (hasCkp) children.push(_encodeCertifiedKeyPair(cr.certifiedKeyPair, state));
439
- if (cr.rspInfo != null) children.push(_reqOctets(cr.rspInfo, "CertResponse.rspInfo"));
440
+ if (hasCkp) _push(children,_encodeCertifiedKeyPair(cr.certifiedKeyPair, state));
441
+ if (cr.rspInfo != null) _push(children,_reqOctets(cr.rspInfo, "CertResponse.rspInfo"));
440
442
  return b.sequence(children);
441
443
  }
442
444
 
@@ -446,9 +448,9 @@ function _encodeCertRepMessage(spec, state, arm) {
446
448
  var children = [];
447
449
  if (spec.caPubs != null) {
448
450
  if (!Array.isArray(spec.caPubs) || !spec.caPubs.length) throw _err("cmp/bad-cert-rep", arm + ".caPubs must be a non-empty array of certificate DERs");
449
- children.push(b.explicit(1, b.sequence(spec.caPubs.map(function (c) { return _certRaw(c, "cmp/bad-cert-rep", "a caPubs entry"); }))));
451
+ _push(children,b.explicit(1, b.sequence(spec.caPubs.map(function (c) { return _certRaw(c, "cmp/bad-cert-rep", "a caPubs entry"); }))));
450
452
  }
451
- children.push(b.sequence(spec.response.map(function (cr) { return _encodeCertResponse(cr, state); })));
453
+ _push(children,b.sequence(spec.response.map(function (cr) { return _encodeCertResponse(cr, state); })));
452
454
  return b.sequence(children);
453
455
  }
454
456
 
@@ -468,11 +470,11 @@ function _encodeRevRepContent(spec) {
468
470
  var children = [b.sequence(spec.status.map(function (si) { return _encodePkiStatusInfo(si, "cmp/bad-rev-rep"); }))];
469
471
  if (spec.revCerts != null) {
470
472
  if (!Array.isArray(spec.revCerts) || !spec.revCerts.length) throw _err("cmp/bad-rev-rep", "rp.revCerts must be a non-empty array of CertId");
471
- children.push(b.explicit(0, b.sequence(spec.revCerts.map(_encodeCertIdRr))));
473
+ _push(children,b.explicit(0, b.sequence(spec.revCerts.map(_encodeCertIdRr))));
472
474
  }
473
475
  if (spec.crls != null) {
474
476
  if (!Array.isArray(spec.crls) || !spec.crls.length) throw _err("cmp/bad-rev-rep", "rp.crls must be a non-empty array of CertificateList DERs");
475
- children.push(b.explicit(1, b.sequence(spec.crls.map(function (c) {
477
+ _push(children,b.explicit(1, b.sequence(spec.crls.map(function (c) {
476
478
  var der = _b.reqDerSequence(c, "crls entry (a CertificateList DER)");
477
479
  try { crl.parse(der); }
478
480
  catch (e) { if (e instanceof CmpError) throw e; throw _err("cmp/bad-rev-rep", "a crls entry is not a valid CRL (CertificateList)", e); }
@@ -486,8 +488,8 @@ function _encodeErrorMsgContent(spec) {
486
488
  if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("cmp/bad-error", "error must be an object { pKIStatusInfo, errorCode?, errorDetails? }");
487
489
  if (spec.pKIStatusInfo == null) throw _err("cmp/bad-error", "error.pKIStatusInfo is required");
488
490
  var children = [_encodePkiStatusInfo(spec.pKIStatusInfo, "cmp/bad-error")];
489
- if (spec.errorCode != null) children.push(b.integer(_reqIdInt(spec.errorCode, "cmp/bad-error", "error.errorCode")));
490
- if (spec.errorDetails != null) children.push(_encodePkiFreeText(spec.errorDetails, "cmp/bad-error", "error.errorDetails"));
491
+ if (spec.errorCode != null) _push(children,b.integer(_reqIdInt(spec.errorCode, "cmp/bad-error", "error.errorCode")));
492
+ if (spec.errorDetails != null) _push(children,_encodePkiFreeText(spec.errorDetails, "cmp/bad-error", "error.errorDetails"));
491
493
  return b.sequence(children);
492
494
  }
493
495
 
@@ -497,7 +499,7 @@ function _encodePollRepContent(list) {
497
499
  if (!pr || typeof pr !== "object" || Buffer.isBuffer(pr)) throw _err("cmp/bad-poll-rep", "each pollRep entry must be an object");
498
500
  if (typeof pr.checkAfter !== "number" || !Number.isInteger(pr.checkAfter) || pr.checkAfter < 0 || pr.checkAfter > 0x7fffffff) throw _err("cmp/bad-poll-rep", "pollRep checkAfter must be a non-negative uint31 delay in seconds (RFC 9810 sec. 5.3.22)");
499
501
  var kids = [b.integer(_reqIdInt(pr.certReqId, "cmp/bad-poll-rep", "pollRep certReqId")), b.integer(BigInt(pr.checkAfter))];
500
- if (pr.reason != null) kids.push(_encodePkiFreeText(pr.reason, "cmp/bad-poll-rep", "pollRep reason"));
502
+ if (pr.reason != null) _push(kids,_encodePkiFreeText(pr.reason, "cmp/bad-poll-rep", "pollRep reason"));
501
503
  return b.sequence(kids);
502
504
  }));
503
505
  }
@@ -506,14 +508,14 @@ function _encodeKeyRecRepContent(spec, state) {
506
508
  if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("cmp/bad-key-rec-rep", "krp must be an object { status, newSigCert?, caCerts?, keyPairHist? }");
507
509
  if (spec.status == null) throw _err("cmp/bad-key-rec-rep", "krp.status is required");
508
510
  var children = [_encodePkiStatusInfo(spec.status, "cmp/bad-key-rec-rep")];
509
- if (spec.newSigCert != null) children.push(b.explicit(0, _certRaw(spec.newSigCert, "cmp/bad-key-rec-rep", "krp.newSigCert")));
511
+ if (spec.newSigCert != null) _push(children,b.explicit(0, _certRaw(spec.newSigCert, "cmp/bad-key-rec-rep", "krp.newSigCert")));
510
512
  if (spec.caCerts != null) {
511
513
  if (!Array.isArray(spec.caCerts) || !spec.caCerts.length) throw _err("cmp/bad-key-rec-rep", "krp.caCerts must be a non-empty array of certificate DERs");
512
- children.push(b.explicit(1, b.sequence(spec.caCerts.map(function (c) { return _certRaw(c, "cmp/bad-key-rec-rep", "a krp.caCerts entry"); }))));
514
+ _push(children,b.explicit(1, b.sequence(spec.caCerts.map(function (c) { return _certRaw(c, "cmp/bad-key-rec-rep", "a krp.caCerts entry"); }))));
513
515
  }
514
516
  if (spec.keyPairHist != null) {
515
517
  if (!Array.isArray(spec.keyPairHist) || !spec.keyPairHist.length) throw _err("cmp/bad-key-rec-rep", "krp.keyPairHist must be a non-empty array of CertifiedKeyPair");
516
- children.push(b.explicit(2, b.sequence(spec.keyPairHist.map(function (ckp) { return _encodeCertifiedKeyPair(ckp, state); }))));
518
+ _push(children,b.explicit(2, b.sequence(spec.keyPairHist.map(function (ckp) { return _encodeCertifiedKeyPair(ckp, state); }))));
517
519
  }
518
520
  return b.sequence(children);
519
521
  }
@@ -891,7 +893,7 @@ async function _build(message, opts) {
891
893
  var protectionBits = await prot.computeBits(protectedPartDer);
892
894
  var msgChildren = [headerTLV, bodyTLV, b.explicit(0, protectionBits)];
893
895
  var extraCertsDers = _collectExtraCerts(opts, prot.certDer);
894
- if (extraCertsDers.length) msgChildren.push(b.explicit(1, b.sequence(extraCertsDers)));
896
+ if (extraCertsDers.length) _push(msgChildren,b.explicit(1, b.sequence(extraCertsDers)));
895
897
  var der = b.sequence(msgChildren);
896
898
 
897
899
  cmp.parse(der);
@@ -905,14 +907,14 @@ async function _build(message, opts) {
905
907
 
906
908
  function _collectExtraCerts(opts, protCertDer) {
907
909
  var out = [];
908
- if (protCertDer != null) out.push(b.raw(protCertDer));
910
+ if (protCertDer != null) _push(out,b.raw(protCertDer));
909
911
  if (opts.extraCerts != null) {
910
912
  if (!Array.isArray(opts.extraCerts)) throw _err("cmp/bad-extra-certs", "opts.extraCerts must be an array of certificate DERs");
911
913
  opts.extraCerts.forEach(function (c) {
912
914
  var der = _b.reqDerSequence(c, "extraCerts entry (a Certificate DER)");
913
915
  try { x509.parse(der); }
914
916
  catch (e) { if (e instanceof CmpError) throw e; throw _err("cmp/bad-extra-certs", "an extraCerts entry is not a valid X.509 certificate", e); }
915
- out.push(b.raw(der));
917
+ _push(out,b.raw(der));
916
918
  });
917
919
  }
918
920
  return out;
@@ -15,6 +15,10 @@ var crmfSign = require("./crmf-sign");
15
15
  var cmpBuild = require("./cmp-build");
16
16
  var csr = require("./schema-csr");
17
17
  var guard = require("./guard-all");
18
+ /** @internal The append every list here is built with: `push` stores at the index and a store
19
+ * consults a setter inherited there, and one of these lists is the accumulated CA certificates a
20
+ * later leg is authenticated against. */
21
+ var _push = guard.list.append;
18
22
  var compositeSig = require("./composite-sig");
19
23
  var constants = require("./constants");
20
24
  var webcrypto = require("./webcrypto");
@@ -34,7 +38,7 @@ function setEngine(engine) { _engine = engine; }
34
38
  var HASHLESS_SIG_OIDS = Object.create(null);
35
39
  (function () {
36
40
  var names = ["Ed25519", "Ed448", "id-ml-dsa-44", "id-ml-dsa-65", "id-ml-dsa-87"];
37
- ["sha2", "shake"].forEach(function (h) { ["128s", "128f", "192s", "192f", "256s", "256f"].forEach(function (s) { names.push("id-slh-dsa-" + h + "-" + s); }); });
41
+ ["sha2", "shake"].forEach(function (h) { ["128s", "128f", "192s", "192f", "256s", "256f"].forEach(function (s) { _push(names,"id-slh-dsa-" + h + "-" + s); }); });
38
42
  names.forEach(function (n) { var o = oid.byName(n); if (o) HASHLESS_SIG_OIDS[o] = 1; });
39
43
  })();
40
44
  var SIG_OID_TO_HASH = Object.create(null);
@@ -136,11 +140,11 @@ function _asCertList(v) { return v == null ? [] : (Array.isArray(v) ? guard.list
136
140
  function _boundedPool(base, added) {
137
141
  var ceiling = constants.LIMITS.PATH_BUILD_MAX_CANDIDATES;
138
142
  var seen = Object.create(null), distinctBase = [];
139
- base.forEach(function (c) { var k = _certIdentity(c); if (k == null) { distinctBase.push(c); return; } if (!seen[k]) { seen[k] = 1; distinctBase.push(c); } });
143
+ base.forEach(function (c) { var k = _certIdentity(c); if (k == null) { _push(distinctBase,c); return; } if (!seen[k]) { seen[k] = 1; _push(distinctBase,c); } });
140
144
  var room = ceiling - distinctBase.length;
141
145
  if (room <= 0) return distinctBase;
142
146
  var useful = [];
143
- added.forEach(function (c) { var k = _certIdentity(c); if (k != null && seen[k]) return; if (k != null) seen[k] = 1; useful.push(c); });
147
+ added.forEach(function (c) { var k = _certIdentity(c); if (k != null && seen[k]) return; if (k != null) seen[k] = 1; _push(useful,c); });
144
148
  return distinctBase.concat(useful.slice(0, room));
145
149
  }
146
150
  function _certIdentity(cert) {
@@ -228,7 +232,7 @@ function _responseExtraCerts(responseBytes) {
228
232
  seen[key] = true;
229
233
  try { x509.parse(c); }
230
234
  catch (_e) { continue; }
231
- out.push(Buffer.from(c));
235
+ _push(out,Buffer.from(c));
232
236
  }
233
237
  return out;
234
238
  }
@@ -682,7 +686,13 @@ function session(opts) {
682
686
  if (!Buffer.isBuffer(c)) return;
683
687
  var k = c.toString("base64");
684
688
  if (caPubsSeen[k]) {
685
- if (isGrantLeg) { for (var pi = 0; pi < caPubsAccum.length; pi++) { if (caPubsAccum[pi].toString("base64") === k) { guard.list.append(caPubsAccum, caPubsAccum.splice(pi, 1)[0]); if (pi < caPubsWaitingCount) caPubsWaitingCount--; break; } } }
689
+ /** @internal The entry is read, removed and appended as three steps rather than through
690
+ * `splice`. `splice` RETURNS what it removed, so it builds that result through
691
+ * `ArraySpeciesCreate`, which reads the receiver's `constructor` and then its
692
+ * `Symbol.species`: a getter installed on `Array.prototype.constructor` is handed this
693
+ * accumulator as its `this` while the move is in progress, and the list holds the CA
694
+ * certificates a later leg is authenticated against. */
695
+ if (isGrantLeg) { for (var pi = 0; pi < caPubsAccum.length; pi++) { if (caPubsAccum[pi].toString("base64") === k) { var moved = caPubsAccum[pi]; guard.list.removeAt(caPubsAccum, pi); guard.list.append(caPubsAccum, moved); if (pi < caPubsWaitingCount) caPubsWaitingCount--; break; } } }
686
696
  return;
687
697
  }
688
698
  try { x509.parse(c); } catch (e) { throw _err("cmp/bad-cert-response", "an authenticated caPubs entry is not a valid X.509 certificate", e); }
@@ -963,10 +973,10 @@ function session(opts) {
963
973
  async function _validateLeaf(leaf, caPubs) {
964
974
  if (_engine == null || opts.trustAnchors == null) return;
965
975
  var caPubsList = [];
966
- if (Array.isArray(caPubs)) caPubs.forEach(function (c) { if (Buffer.isBuffer(c)) caPubsList.push(c); });
976
+ if (Array.isArray(caPubs)) caPubs.forEach(function (c) { if (Buffer.isBuffer(c)) _push(caPubsList,c); });
967
977
  var added = _asCertList(opts.intermediates);
968
- if (Buffer.isBuffer(cachedSignerCert)) added.push(cachedSignerCert);
969
- cachedChain.forEach(function (c) { if (Buffer.isBuffer(c)) added.push(c); });
978
+ if (Buffer.isBuffer(cachedSignerCert)) _push(added,cachedSignerCert);
979
+ cachedChain.forEach(function (c) { if (Buffer.isBuffer(c)) _push(added,c); });
970
980
  var pool = _boundedPool(caPubsList, added);
971
981
  var res;
972
982
  try { res = await _engine.build(leaf, { trustAnchors: _asCertList(opts.trustAnchors), intermediates: pool, validate: true, time: opts.time != null ? opts.time : new Date() }); }
@@ -1395,7 +1405,7 @@ function session(opts) {
1395
1405
  if (limit.total !== null && total > limit.total) {
1396
1406
  throw _err("cmp/bad-input", "the resumeToken " + name + " exceeds the " + limit.total + "-byte pool a transaction holds");
1397
1407
  }
1398
- out.push(der);
1408
+ _push(out,der);
1399
1409
  }
1400
1410
  return out;
1401
1411
  }
@@ -4,7 +4,6 @@
4
4
  // @internal
5
5
  // @primitive pki.cms.decrypt block live in cms-verify.js, which re-exports this function.
6
6
 
7
- var nodeCrypto = require("crypto");
8
7
  var asn1 = require("./asn1-der");
9
8
  var oid = require("./oid");
10
9
  var x509 = require("./schema-x509");
@@ -121,10 +120,10 @@ function _selectCandidates(recips, km, opts) {
121
120
  for (var k = 0; k < recips.length; k++) {
122
121
  var r = recips[k];
123
122
  if (want === "asym" && (r.type === "ktri" || r.type === "kari" || r.type === "ori")) {
124
- if (cert && _ridMatches(r, cert)) out.push({ ri: r, index: k });
125
- } else if (want === "pwri" && r.type === "pwri") { out.push({ ri: r, index: k }); }
123
+ if (cert && _ridMatches(r, cert)) intrinsic.append(out, { ri: r, index: k });
124
+ } else if (want === "pwri" && r.type === "pwri") { intrinsic.append(out, { ri: r, index: k }); }
126
125
  else if (want === "kekri" && r.type === "kekri") {
127
- if (km.kekId == null || _kekIdMatches(r, km.kekId)) out.push({ ri: r, index: k });
126
+ if (km.kekId == null || _kekIdMatches(r, km.kekId)) intrinsic.append(out, { ri: r, index: k });
128
127
  }
129
128
  }
130
129
  if (!out.length) throw _err("cms/no-matching-recipient", "no recipient matches the supplied key material");
@@ -235,8 +234,8 @@ async function _ktriCek(ri, km) {
235
234
  return Buffer.from(await subtle.decrypt({ name: "RSA-OAEP" }, pub, ri.encryptedKey));
236
235
  }
237
236
  if (kea.oid === O("rsaEncryption")) {
238
- var keyObj = nodeCrypto.createPrivateKey({ key: k.der, format: "der", type: "pkcs8" });
239
- try { return nodeCrypto.privateDecrypt({ key: keyObj, padding: guard.crypto.padding.RSA_PKCS1 }, ri.encryptedKey); }
237
+ var keyObj = guard.crypto.privateKey({ key: k.der, format: "der", type: "pkcs8" });
238
+ try { return guard.crypto.privateDecrypt({ key: keyObj, padding: guard.crypto.padding.RSA_PKCS1 }, ri.encryptedKey); }
240
239
  catch (_e) {
241
240
  return null;
242
241
  }
@@ -339,7 +338,7 @@ async function _pwriCek(ri, km, opts) {
339
338
  var iv = asn1.read.octetString(inner.children[1]);
340
339
  var pw = pbes2.passwordBytesOwned(km.password, _err, "cms");
341
340
  var kek;
342
- try { kek = nodeCrypto.pbkdf2Sync(pw.bytes, pb.salt, pb.iterations, innerBits / 8, pb.prfNode); }
341
+ try { kek = guard.crypto.pbkdf2(pw.bytes, pb.salt, pb.iterations, innerBits / 8, pb.prfNode); }
343
342
  finally { if (pw.owned) guard.secret.zeroize(pw.bytes, CmsError, "cms/bad-input", "the password encoding"); }
344
343
  try {
345
344
  return _pwriUnwrap(kek, ri.encryptedKey, iv, innerBits);
@@ -421,7 +420,7 @@ async function _openContent(parsed, eci, cek, ct, streamMode) {
421
420
  }
422
421
  if (eci.encryptedContent == null) throw _err("cms/no-encrypted-content", "the message has no encryptedContent (detached; supply it out of band)");
423
422
  var substitute = null;
424
- if (cek == null || cek.length !== keyBits / 8) { substitute = nodeCrypto.randomBytes(keyBits / 8); cek = substitute; }
423
+ if (cek == null || cek.length !== keyBits / 8) { substitute = guard.crypto.randomBytes(keyBits / 8); cek = substitute; }
425
424
  try {
426
425
  if (ct === "authEnvelopedData") {
427
426
  var aad = parsed.authAttrsBytes != null ? _explicitSetOf(parsed.authAttrsBytes) : Buffer.alloc(0);
@@ -461,9 +460,9 @@ async function _openContent(parsed, eci, cek, ct, streamMode) {
461
460
  }
462
461
  function _gcmOpen(cek, nonce, ct, tag, aad, keyBits, icvLen) {
463
462
  if (!tag || tag.length !== icvLen) throw _fail();
464
- var d = nodeCrypto.createDecipheriv("aes-" + keyBits + "-gcm", cek, nonce, { authTagLength: icvLen });
465
- d.setAuthTag(tag);
466
- if (aad && aad.length) d.setAAD(aad);
463
+ var d = guard.crypto.decipher("aes-" + keyBits + "-gcm", cek, nonce, { authTagLength: icvLen });
464
+ guard.crypto.decipherSetAuthTag(d, tag);
465
+ if (aad && aad.length) guard.crypto.transformSetAAD(d, aad);
467
466
  return guard.secret.cipherFinish(d, ct, CmsError, "cms/decrypt-failed", "the recovered content");
468
467
  }
469
468
 
@@ -543,7 +542,7 @@ async function _decryptPbes2(parsed, eci, km, opts) {
543
542
  if (!keyBits) throw _err("cms/unsupported-algorithm", "unsupported PBES2 content cipher " + encOid);
544
543
  var pwE = pbes2.passwordBytesOwned(km.password, _err, "cms");
545
544
  var key;
546
- try { key = nodeCrypto.pbkdf2Sync(pwE.bytes, pb.salt, pb.iterations, keyBits / 8, pb.prfNode); }
545
+ try { key = guard.crypto.pbkdf2(pwE.bytes, pb.salt, pb.iterations, keyBits / 8, pb.prfNode); }
547
546
  finally { if (pwE.owned) guard.secret.zeroize(pwE.bytes, CmsError, "cms/bad-input", "the password encoding"); }
548
547
  try { return _originFields({ content: opts.stream === true ? _cbcStream(key, iv, eci.encryptedContent, keyBits) : pbes2.cbcDecrypt(key, iv, eci.encryptedContent, keyBits, CmsError, "cms/decrypt-failed"), contentType: eci.contentType, contentTypeName: oid.name(eci.contentType) || eci.contentType, recipientType: "password", recipientIndex: -1, contentEncryptionAlgorithm: oid.name(encOid) || encOid, authenticated: false }, null, null); }
549
548
  catch (_e) { throw _fail(); }
@@ -563,19 +562,23 @@ async function _aesKwUnwrap(kek, wrapped) {
563
562
  guard.secret.zeroize(new Uint8Array(rawAb), CmsError, "cms/bad-input", "the unwrapped content key");
564
563
  }
565
564
  }
565
+ /** @internal Both KDF-input structures APPEND by defining the index. A store at an index the list
566
+ * has no own property at consults a setter inherited from the array prototype, so an accessor there
567
+ * would decide the SharedInfo these bytes become and derive a different KEK from the same shared
568
+ * secret. */
566
569
  function _eccSharedInfo(wrapName, ukm, kekBytes) {
567
570
  var kids = [b.sequence([b.oid(O(wrapName))])];
568
- if (ukm) kids.push(b.explicit(0, b.octetString(ukm)));
571
+ if (ukm) intrinsic.append(kids, b.explicit(0, b.octetString(ukm)));
569
572
  /** @internal The SuppPubInfo key length is written with the capture, for the same reason the
570
573
  * encrypt side does it: this is KDF input, and a replaced write derives a different KEK from the
571
574
  * same shared secret. */
572
575
  var supp = Buffer.alloc(4); intrinsic.writeUInt32BE(supp, kekBytes * 8, 0);
573
- kids.push(b.explicit(2, b.octetString(supp)));
576
+ intrinsic.append(kids, b.explicit(2, b.octetString(supp)));
574
577
  return b.sequence(kids);
575
578
  }
576
579
  function _kemOtherInfo(wrapName, kekBytes, ukm) {
577
580
  var kids = [b.sequence([b.oid(O(wrapName))]), b.integer(BigInt(kekBytes))];
578
- if (ukm) kids.push(b.explicit(0, b.octetString(ukm)));
581
+ if (ukm) intrinsic.append(kids, b.explicit(0, b.octetString(ukm)));
579
582
  return b.sequence(kids);
580
583
  }
581
584
  function _pwriUnwrap(kek, wrapped, iv, keyBits) {
@@ -584,13 +587,13 @@ function _pwriUnwrap(kek, wrapped, iv, keyBits) {
584
587
  var n = wrapped.length;
585
588
  var lastDec = null, pass1 = null, body = null;
586
589
  try {
587
- var ecb = nodeCrypto.createDecipheriv("aes-" + keyBits + "-ecb", kek, Buffer.alloc(0)); ecb.setAutoPadding(false);
590
+ var ecb = guard.crypto.decipher("aes-" + keyBits + "-ecb", kek, Buffer.alloc(0)); guard.crypto.transformNoPadding(ecb);
588
591
  lastDec = guard.secret.cipherFinish(ecb, wrapped.subarray(n - blk), CmsError, "cms/decrypt-failed", "the recovered CBC last block");
589
592
  var iv2 = Buffer.alloc(blk);
590
593
  for (var i = 0; i < blk; i++) iv2[i] = lastDec[i] ^ wrapped[n - 2 * blk + i];
591
- var d1 = nodeCrypto.createDecipheriv(alg, kek, iv2); d1.setAutoPadding(false);
594
+ var d1 = guard.crypto.decipher(alg, kek, iv2); guard.crypto.transformNoPadding(d1);
592
595
  pass1 = guard.secret.cipherFinish(d1, wrapped, CmsError, "cms/decrypt-failed", "the PWRI first-pass plaintext");
593
- var d2 = nodeCrypto.createDecipheriv(alg, kek, iv); d2.setAutoPadding(false);
596
+ var d2 = guard.crypto.decipher(alg, kek, iv); guard.crypto.transformNoPadding(d2);
594
597
  body = guard.secret.cipherFinish(d2, pass1, CmsError, "cms/decrypt-failed", "the PWRI plaintext block");
595
598
  var count = body[0];
596
599
  if (count < 1 || count + 4 > body.length) throw _fail();
@@ -648,7 +651,7 @@ function _originatorSpki(originator) {
648
651
  if (!originator || originator.form !== "originatorKey") throw _err("cms/unsupported-algorithm", "kari requires an originatorKey (ephemeral-static ECDH)");
649
652
  var v = originator.value;
650
653
  var algKids = [b.oid(v.algorithm.oid)];
651
- if (v.algorithm.parameters != null) algKids.push(b.raw(v.algorithm.parameters));
654
+ if (v.algorithm.parameters != null) intrinsic.append(algKids, b.raw(v.algorithm.parameters));
652
655
  return b.sequence([b.sequence(algKids), b.bitString(v.publicKey.bytes, v.publicKey.unusedBits)]);
653
656
  }
654
657
  var MONT = intrinsic.create(null); MONT[O("X25519")] = { name: "X25519", hkdf: "SHA-256" }; MONT[O("X448")] = { name: "X448", hkdf: "SHA-512" };
@@ -666,8 +669,9 @@ function _ecCurveFromCert(cert) {
666
669
  function _ecCurveFromPrivateKey(keyDer) {
667
670
  var spki;
668
671
  try {
669
- spki = nodeCrypto.createPublicKey({ key: keyDer, format: "der", type: "pkcs8" })
670
- .export({ format: "der", type: "spki" });
672
+ spki = guard.crypto.exportKey(
673
+ guard.crypto.publicKey({ key: keyDer, format: "der", type: "pkcs8" }),
674
+ { format: "der", type: "spki" });
671
675
  } catch (_e) { return null; } // allow:swallow-unverified a key this runtime cannot read names no curve
672
676
  var alg = asn1.decode(spki).children[0];
673
677
  if (asn1.read.oid(alg.children[0]) !== O("ecPublicKey") || alg.children.length < 2) return null;
@@ -710,7 +714,17 @@ async function _verifyAuthenticatedData(parsed, km, opts, requireProtection) {
710
714
  guard.der.assertParams(parsed.digestAlgorithm.parameters, "absentOrNull", _err,
711
715
  "cms/unsupported-algorithm", parsed.digestAlgorithm.name + " digestAlgorithm (RFC 5754 sec. 2)");
712
716
  preimage = _explicitSetOf(parsed.authAttrsBytes);
713
- var mdAttr = (parsed.authAttrs || []).filter(function (a) { return a.type === O("messageDigest"); })[0];
717
+ /** @internal The selection returns the first matching attribute or null. `filter(...)[0]` indexes
718
+ * a result that is EMPTY when the attribute is absent, and index 0 of an empty array answers
719
+ * from the array prototype, so a value installed there would supply the digest this comparison
720
+ * is made against. The refusal restates an invariant the parse already holds: an
721
+ * AuthenticatedData with authAttrs is walked through the content-binding check, which requires
722
+ * the message-digest attribute (`cms/missing-message-digest`), so this is not reachable from a
723
+ * message and is here so the read below cannot be made on something that is not an attribute. */
724
+ var mdAttr = guard.list.firstMatch(parsed.authAttrs || [], function (a) { return a.type === O("messageDigest"); });
725
+ if (!mdAttr || mdAttr.values.length !== 1) {
726
+ throw _err("cms/bad-auth-attrs", "authenticated attributes must carry exactly one message-digest attribute (RFC 5652 sec. 9.2)");
727
+ }
714
728
  mdCheck = { hash: dHash, declared: asn1.read.octetString(asn1.decode(mdAttr.values[0])) };
715
729
  /** @internal RFC 6211 sec. 3.2 on this content type: the two comparisons are what make the
716
730
  * outer `digestAlgorithm` and `macAlgorithm` fields mean anything, since the MAC input is the
@@ -742,7 +756,7 @@ async function _verifyAuthenticatedData(parsed, km, opts, requireProtection) {
742
756
  _assertSupported(candidates[ci].ri, km);
743
757
  var macKey = await _acquireCek(candidates[ci].ri, km, opts);
744
758
  var macSubstitute = null;
745
- if (macKey == null || macKey.length < MAC_KEY_MIN_OCTETS) macSubstitute = nodeCrypto.randomBytes(MAC_KEY_MIN_OCTETS);
759
+ if (macKey == null || macKey.length < MAC_KEY_MIN_OCTETS) macSubstitute = guard.crypto.randomBytes(MAC_KEY_MIN_OCTETS);
746
760
  try {
747
761
  var key = await subtle.importKey("raw", macSubstitute || macKey, { name: "HMAC", hash: hash }, false, ["verify"]);
748
762
  if (!(await _subtleVerify(subtle, { name: "HMAC" }, key, Buffer.from(parsed.mac), preimage))) throw _fail();
package/lib/cms-digest.js CHANGED
@@ -26,7 +26,6 @@
26
26
  * attached or detached, constant-time comparison, fail-closed.
27
27
  */
28
28
 
29
- var nodeCrypto = require("node:crypto");
30
29
  var oid = require("./oid");
31
30
  var schemaCms = require("./schema-cms");
32
31
  var frameworkError = require("./framework-error");
@@ -101,7 +100,7 @@ async function _digest(content, opts) {
101
100
  var ctOid = O(ctName);
102
101
  if (!ctOid) throw _err("cms/bad-input", "opts.contentType is not a known OID name: " + guard.text.showValue(ctName));
103
102
 
104
- var value = nodeCrypto.createHash(NODE_DIGEST[alg]).update(raw).digest();
103
+ var value = guard.crypto.digest(NODE_DIGEST[alg], raw);
105
104
  var eciChildren = opts.detached === true
106
105
  ? [b.oid(ctOid)]
107
106
  : [b.oid(ctOid), b.explicit(0, b.octetString(raw))];
@@ -176,7 +175,7 @@ async function _verifyDigest(input, opts) {
176
175
  var covered = embedded != null
177
176
  ? guard.bytes.snapshotSource(embedded, CmsError, "cms/bad-input", "the encapsulated content")
178
177
  : supplied;
179
- var recomputed = nodeCrypto.createHash(NODE_DIGEST[alg]).update(covered).digest();
178
+ var recomputed = guard.crypto.digest(NODE_DIGEST[alg], covered);
180
179
  var matched = guard.crypto.constantTimeEqual(recomputed, parsed.digest);
181
180
  return guard.verdict.of({
182
181
  valid: matched,