@blamejs/pki 0.8.61 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/MIGRATING.md +46 -0
  3. package/README.md +8 -1
  4. package/index.js +55 -26
  5. package/lib/acme.js +5 -5
  6. package/lib/asn1-der.js +1 -1
  7. package/lib/attrcert-sign.js +2 -2
  8. package/lib/cbor-det.js +4 -1
  9. package/lib/cmc-build.js +1 -1
  10. package/lib/cmp-build.js +5 -5
  11. package/lib/cmp-session.js +6 -3
  12. package/lib/cmp-verify.js +1 -1
  13. package/lib/cms-compress.js +5 -2
  14. package/lib/cms-decrypt.js +2 -2
  15. package/lib/cms-encrypt.js +2 -2
  16. package/lib/cms-sign.js +2 -2
  17. package/lib/constants.js +3 -0
  18. package/lib/crl-sign.js +3 -3
  19. package/lib/crmf-sign.js +1 -1
  20. package/lib/csr-sign.js +1 -1
  21. package/lib/ct.js +14 -13
  22. package/lib/est.js +101 -29
  23. package/lib/framework-error.js +1 -1
  24. package/lib/guard-bytes.js +1 -1
  25. package/lib/guard-limits.js +3 -2
  26. package/lib/hpke.js +2 -2
  27. package/lib/http-retry-after.js +4 -1
  28. package/lib/http-transport.js +6 -6
  29. package/lib/inspect.js +9 -4
  30. package/lib/jose.js +3 -3
  31. package/lib/merkle.js +4 -4
  32. package/lib/mime.js +124 -17
  33. package/lib/ocsp.js +2 -2
  34. package/lib/path-validate.js +3 -3
  35. package/lib/pbes2.js +8 -4
  36. package/lib/pkcs12-build.js +5 -5
  37. package/lib/scep.js +1 -1
  38. package/lib/schema-engine.js +12 -12
  39. package/lib/schema-pkix.js +12 -12
  40. package/lib/sign-scheme.js +2 -2
  41. package/lib/sigstore.js +1 -1
  42. package/lib/smime.js +11 -12
  43. package/lib/tlog.js +2 -2
  44. package/lib/tls-cert-compress.js +3 -3
  45. package/lib/tsp-sign.js +6 -6
  46. package/lib/tuf.js +3 -3
  47. package/lib/webauthn-mds.js +1 -1
  48. package/lib/webauthn.js +1 -1
  49. package/lib/x509-sign.js +3 -3
  50. package/package.json +1 -1
  51. package/sbom.cdx.json +6 -6
package/lib/jose.js CHANGED
@@ -325,7 +325,7 @@ function assertPublicJwk(jwk) {
325
325
  */
326
326
  var _VERIFY_KEYS = intrinsic.assign(intrinsic.create(null), { key: 1, profile: 1 });
327
327
  async function verify(jws, opts) {
328
- opts = opts || {};
328
+ opts = opts || intrinsic.create(null);
329
329
  guard.identifier.assertKnownKeys(opts, _VERIFY_KEYS, E, "jose/bad-input", "unknown pki.jose.verify option ");
330
330
  /** @internal opts.key is examined several times: the type gate, the RFC 7638 thumbprint comparison
331
331
  * against the embedded jwk, and the key the signature is verified under. An option reached through
@@ -456,7 +456,7 @@ function _fixedPayload(supplied) {
456
456
  }
457
457
 
458
458
  async function sign(opts) {
459
- opts = opts || {};
459
+ opts = opts || intrinsic.create(null);
460
460
  guard.identifier.assertKnownKeys(opts, _SIGN_KEYS, E, "jose/bad-input", "unknown pki.jose.sign option ");
461
461
  var fixedPayload = _fixedPayload(opts.payload);
462
462
  var headerJson;
@@ -496,7 +496,7 @@ async function sign(opts) {
496
496
  var protectedB64 = b64uEncode(headerBytes);
497
497
  var payloadB64 = payload.length === 0 ? "" : b64uEncode(payload);
498
498
  var signingInput = _bufferFrom(protectedB64 + "." + payloadB64, "ascii");
499
- var jwk = header.jwk || opts.jwk || {};
499
+ var jwk = header.jwk || opts.jwk || intrinsic.create(null);
500
500
  /** @internal `suppliedKey` is the reading taken at the top, so the key adopted for signing, the key the
501
501
  * hash-to-algorithm check approved and the key the expected signature width is computed from are all
502
502
  * one key. */
package/lib/merkle.js CHANGED
@@ -274,7 +274,7 @@ function emptyRootHash() {
274
274
  */
275
275
  var _INCLUSION_KEYS = _assign(_create(null), { leafIndex: 1, treeSize: 1, leafHash: 1, rootHash: 1, proof: 1 });
276
276
  function verifyInclusion(opts) {
277
- opts = opts || {};
277
+ opts = opts || _create(null);
278
278
  guard.identifier.assertKnownKeys(opts, _INCLUSION_KEYS, function (c, m) { return new MerkleError(c, m); },
279
279
  "merkle/bad-input", "unknown verifyInclusion option ");
280
280
  var leafIndex = _coerceCoord(opts.leafIndex, "leafIndex");
@@ -346,7 +346,7 @@ function verifyInclusion(opts) {
346
346
  */
347
347
  var _CONSISTENCY_KEYS = _assign(_create(null), { oldSize: 1, newSize: 1, oldRoot: 1, newRoot: 1, proof: 1 });
348
348
  function verifyConsistency(opts) {
349
- opts = opts || {};
349
+ opts = opts || _create(null);
350
350
  guard.identifier.assertKnownKeys(opts, _CONSISTENCY_KEYS, function (c, m) { return new MerkleError(c, m); },
351
351
  "merkle/bad-input", "unknown verifyConsistency option ");
352
352
  var oldSize = _coerceCoord(opts.oldSize, "oldSize");
@@ -456,7 +456,7 @@ function root(leafHashes) {
456
456
  */
457
457
  var _INCLUSION_PROOF_KEYS = _assign(_create(null), { leafHashes: 1, leafIndex: 1 });
458
458
  function inclusionProof(opts) {
459
- opts = opts || {};
459
+ opts = opts || _create(null);
460
460
  guard.identifier.assertKnownKeys(opts, _INCLUSION_PROOF_KEYS, _merkleErr,
461
461
  "merkle/bad-input", "unknown inclusionProof option ");
462
462
  var leaves = _leafArray(opts.leafHashes, "leafHashes");
@@ -498,7 +498,7 @@ function inclusionProof(opts) {
498
498
  */
499
499
  var _CONSISTENCY_PROOF_KEYS = _assign(_create(null), { leafHashes: 1, oldSize: 1 });
500
500
  function consistencyProof(opts) {
501
- opts = opts || {};
501
+ opts = opts || _create(null);
502
502
  guard.identifier.assertKnownKeys(opts, _CONSISTENCY_PROOF_KEYS, _merkleErr,
503
503
  "merkle/bad-input", "unknown consistencyProof option ");
504
504
  var leaves = _leafArray(opts.leafHashes, "leafHashes");
package/lib/mime.js CHANGED
@@ -26,6 +26,9 @@ var _push = guard.list.append;
26
26
  var CRLF = Buffer.from("\r\n");
27
27
 
28
28
  function _buf(v, E, code, label) { return guard.bytes.view(v, E, code, label); }
29
+ /** @internal `guard.limits.counter` throws `E(code, ...)`, and every consumer of this module hands in
30
+ * its error CLASS. */
31
+ function _factory(E) { return function (c, m) { return new E(c, m); }; }
29
32
 
30
33
  function _splitPoint(bytes) {
31
34
  for (var i = 0; i < bytes.length; i++) {
@@ -57,27 +60,83 @@ function _stripLeadingHtab(s) {
57
60
  return s.slice(i);
58
61
  }
59
62
 
60
- function _unfoldHeaders(headerText) {
61
- var lines = _toLf(headerText).split("\n");
63
+ /** @internal The end of the line starting at `from`, and where the next one starts. A line is ended by
64
+ * CRLF, by a lone CR or by LF, which is the separator set `_toLf` followed by a split produces. */
65
+ function _lineEnd(s, from) {
66
+ for (var i = from; i < s.length; i++) {
67
+ var c = s.charCodeAt(i);
68
+ if (c === 0x0a) return { end: i, next: i + 1 };
69
+ if (c === 0x0d) return { end: i, next: (s.charCodeAt(i + 1) === 0x0a) ? i + 2 : i + 1 };
70
+ }
71
+ return { end: s.length, next: s.length };
72
+ }
73
+
74
+ /** @internal One line is cut at a time and EVERY line is charged, folded continuations and empty lines
75
+ * included, so the refusal costs the cap rather than the input. Splitting the whole header area first
76
+ * and counting fields afterwards read a 16 MiB area of 2,097,150 one-line fields in 1114 ms and
77
+ * 653 MiB of resident memory before the count refused it, and charging only fields left a 16 MiB area
78
+ * of 1,864,130 continuation lines folding into one 13 MB value in 1648 ms without the count ever
79
+ * reaching two. */
80
+ function _unfoldHeaders(headerText, counted) {
62
81
  var out = [];
63
- for (var i = 0; i < lines.length; i++) {
64
- var ln = lines[i];
82
+ for (var at = 0; at < headerText.length;) {
83
+ var cut = _lineEnd(headerText, at);
84
+ var ln = headerText.slice(at, cut.end);
85
+ at = cut.next;
86
+ counted.tick();
65
87
  if (ln === "") continue;
66
- if ((ln[0] === " " || ln[0] === "\t") && out.length) out[out.length - 1] += " " + _stripLeadingHtab(ln);
67
- else _push(out,ln);
88
+ if ((ln.charAt(0) === " " || ln.charAt(0) === "\t") && out.length) {
89
+ out[out.length - 1] += " " + _stripLeadingHtab(ln);
90
+ } else {
91
+ _push(out, ln);
92
+ }
68
93
  }
69
94
  return out;
70
95
  }
71
96
 
72
- function _parseStructured(headerValue) {
73
- var parts = _splitSemicolons(headerValue);
97
+ /**
98
+ * @internal
99
+ * RFC 2045 sec. 5.1 gives a parameter one occurrence, so a header naming one twice has no value this
100
+ * function can resolve: reading the last occurrence and reading the first are both conforming, and they
101
+ * disagree. These values decide what a signature covers (`boundary` sets where the parts begin),
102
+ * whether the entity is accepted (`protocol`, `smime-type`) and which digest is reported (`micalg`), so
103
+ * a repeat is refused here, where the record is built, rather than per parameter at each reader. An
104
+ * occurrence counts whether or not it carries a value, which is the `hp; hp="clear"` form; a single
105
+ * bare attribute still reaches the reader that owns it.
106
+ *
107
+ * What is refused is two readings that produce DIFFERENT VALUES, which is why the two RFC 2231
108
+ * spellings are not treated alike. A plain occurrence beside a starred one of the same attribute,
109
+ * `boundary*=us-ascii''DECOY; boundary=REAL`, gives this reader REAL and an RFC 2231 reader DECOY, so
110
+ * it is refused. Continuation segments alone, `name*0=a; name*1=b`, give this reader NO value for that
111
+ * attribute, so a consumer sees it as absent and the one place absence matters already fails closed:
112
+ * `splitMultipart` refuses an entity with no boundary. Refusing those would reject a conforming
113
+ * message over a parameter that cannot change what the signature covers.
114
+ */
115
+ function _parseStructured(headerValue, E, code, label) {
116
+ var counted = guard.limits.counter(C.LIMITS.MIME_MAX_PARAMS, _factory(E), code, label + " parameter");
117
+ var parts = _splitSemicolons(headerValue, counted);
74
118
  var type = _stripComments(parts[0]).trim().toLowerCase();
75
119
  var params = Object.create(null);
120
+ var seenExact = Object.create(null), seenPlain = Object.create(null), seenStarred = Object.create(null);
76
121
  for (var i = 1; i < parts.length; i++) {
77
122
  var p = _stripComments(parts[i]);
78
123
  var eq = p.indexOf("=");
124
+ var name = (eq < 0 ? p : p.slice(0, eq)).trim().toLowerCase();
125
+ if (name === "") continue;
126
+ var base = _baseAttribute(name);
127
+ var starred = base !== name;
128
+ if (seenExact[name] === true) {
129
+ throw new E(code, label + " declares the " + JSON.stringify(name) +
130
+ " parameter more than once, so its value is ambiguous (RFC 2045 sec. 5.1)");
131
+ }
132
+ if (starred ? seenPlain[base] === true : seenStarred[base] === true) {
133
+ throw new E(code, label + " spells the " + JSON.stringify(base) +
134
+ " parameter both plainly and as an RFC 2231 extended or continued value, and the two spellings " +
135
+ "carry different values (RFC 2231 sec. 7)");
136
+ }
137
+ seenExact[name] = true;
138
+ if (starred) seenStarred[base] = true; else seenPlain[base] = true;
79
139
  if (eq < 0) continue;
80
- var name = p.slice(0, eq).trim().toLowerCase();
81
140
  var val = p.slice(eq + 1).trim();
82
141
  if (val.length >= 2 && val[0] === '"' && val[val.length - 1] === '"') val = val.slice(1, -1);
83
142
  params[name] = val;
@@ -99,7 +158,28 @@ function _stripComments(s) {
99
158
  return out;
100
159
  }
101
160
 
102
- function _splitSemicolons(s) {
161
+ /** @internal The attribute an RFC 2231 name belongs to. Sections 3 and 4 spell one parameter three
162
+ * ways, `name`, `name*` for an extended value and `name*0` / `name*1` for a continuation, and
163
+ * section 7 makes them the same logical parameter. This module assembles neither starred form, so a
164
+ * reader that does takes a different value from the same bytes: measured, `boundary*=us-ascii''DECOY;
165
+ * boundary=REAL` verified here while an RFC 2231 reader splits the body on DECOY. Comparing the
166
+ * attribute rather than the spelling is what makes the two the same occurrence. A leading asterisk
167
+ * is a name in its own right and keeps it. */
168
+ function _baseAttribute(name) {
169
+ var star = name.indexOf("*");
170
+ return star > 0 ? name.slice(0, star) : name;
171
+ }
172
+
173
+ /** @internal The first segment is the media type rather than a parameter, so it is not charged. The
174
+ * charge comes BEFORE the segment is stored, so the refusal costs the cap and not the input: charging
175
+ * the segments after the split instead read a 3.8 MiB Content-Type of 1,000,000 parameters in 192 ms
176
+ * and 73 MiB of resident memory before the same cap refused it. */
177
+ function _pushSegment(out, seg, counted) {
178
+ if (counted !== undefined && out.length > 0) counted.tick();
179
+ _push(out, seg);
180
+ }
181
+
182
+ function _splitSemicolons(s, counted) {
103
183
  var out = [], cur = "", inQ = false, depth = 0;
104
184
  for (var i = 0; i < s.length; i++) {
105
185
  var ch = s[i];
@@ -107,21 +187,29 @@ function _splitSemicolons(s) {
107
187
  else if (ch === '"' && depth === 0) { inQ = !inQ; cur += ch; }
108
188
  else if (ch === "(" && !inQ) { depth++; cur += ch; }
109
189
  else if (ch === ")" && !inQ && depth > 0) { depth--; cur += ch; }
110
- else if (ch === ";" && !inQ && depth === 0) { _push(out,cur); cur = ""; }
190
+ else if (ch === ";" && !inQ && depth === 0) { _pushSegment(out, cur, counted); cur = ""; }
111
191
  else cur += ch;
112
192
  }
113
- _push(out,cur);
193
+ _pushSegment(out, cur, counted);
114
194
  return out;
115
195
  }
116
196
 
117
197
  function parse(input, E, code) {
118
- var bytes = _buf(input, E, code, "the MIME entity");
119
- if (bytes.length > C.LIMITS.MIME_MAX_BYTES) throw new E(code, "MIME entity exceeds the size cap");
198
+ /** @internal A snapshot, not a view: the record below holds `subarray`s of these bytes and a caller
199
+ * reads them back after the parse returns, so a view would let the caller's own later write change
200
+ * what the record says the entity was. Measured on the shipped verb: `pki.smime.verify` returned
201
+ * `valid: true` with `content` sharing the caller's store, and a write into that store afterwards
202
+ * changed the bytes the caller read as verified. The copy is byte-identical, so the octets a
203
+ * signature covers are unchanged. */
204
+ var viewed = _buf(input, E, code, "the MIME entity");
205
+ guard.limits.byteCap(viewed, C.LIMITS.MIME_MAX_BYTES, _factory(E), code, "the MIME entity");
206
+ var bytes = guard.bytes.snapshot(viewed, E, code, "the MIME entity");
120
207
  var sp = _splitPoint(bytes);
121
208
  var headerBytes = sp ? bytes.subarray(0, sp.headerEnd) : bytes;
122
209
  var bodyBytes = sp ? bytes.subarray(sp.bodyStart) : Buffer.alloc(0);
123
210
  var headerText = guard.text.decode(headerBytes, C.LIMITS.MIME_MAX_BYTES, E, { charset: "latin1", tooLarge: code, badInput: code, label: "the MIME headers" });
124
- var rawHeaders = _unfoldHeaders(headerText);
211
+ var countedHeaders = guard.limits.counter(C.LIMITS.MIME_MAX_HEADERS, _factory(E), code, "the MIME header line");
212
+ var rawHeaders = _unfoldHeaders(headerText, countedHeaders);
125
213
  var headers = [];
126
214
  for (var i = 0; i < rawHeaders.length; i++) {
127
215
  var colon = rawHeaders[i].indexOf(":");
@@ -130,12 +218,29 @@ function parse(input, E, code) {
130
218
  var body = rawHeaders[i].slice(colon + 1);
131
219
  _push(headers,{ name: nm, lname: nm.toLowerCase(), value: body.trim(), rawValue: body.charAt(0) === " " ? body.slice(1) : body });
132
220
  }
133
- function header(name) { var l = name.toLowerCase(); for (var j = 0; j < headers.length; j++) if (headers[j].lname === l) return headers[j].value; return null; }
221
+ /** @internal Resolving a field that occurs more than once means choosing an occurrence, and reading
222
+ * the first and reading the last are both conforming (RFC 5322 sec. 3.6 gives a singleton field one
223
+ * occurrence). The media type decides which reader a body goes to and the transfer encoding decides
224
+ * how its octets are recovered, so a repeat is refused rather than resolved by position. Every
225
+ * occurrence stays in `headers`, where a field that may legally repeat, such as `Received`, is
226
+ * read instead. */
227
+ function header(name) {
228
+ var l = name.toLowerCase(), found = null;
229
+ for (var j = 0; j < headers.length; j++) {
230
+ if (headers[j].lname !== l) continue;
231
+ if (found !== null) {
232
+ throw new E(code, "the entity declares the " + JSON.stringify(headers[j].name) +
233
+ " field more than once, so resolving it to a single value is ambiguous (RFC 5322 sec. 3.6)");
234
+ }
235
+ found = headers[j];
236
+ }
237
+ return found === null ? null : found.value;
238
+ }
134
239
  var ctv = header("content-type");
135
240
  var cte = (header("content-transfer-encoding") || "").trim().toLowerCase() || "7bit";
136
241
  return {
137
242
  headers: headers, header: header,
138
- contentType: ctv != null ? _parseStructured(ctv) : { value: "text/plain", type: "text/plain", params: Object.create(null) },
243
+ contentType: ctv != null ? _parseStructured(ctv, E, code, "the Content-Type") : { value: "text/plain", type: "text/plain", params: Object.create(null) },
139
244
  cte: cte,
140
245
  headerBytes: headerBytes, bodyBytes: bodyBytes, body: bodyBytes, bytes: bytes,
141
246
  };
@@ -158,7 +263,9 @@ function splitMultipart(bodyBytes, boundary, E, code) {
158
263
  if (idx < 0) throw new E(code, "no boundary delimiter found in the multipart body");
159
264
  var pos = _afterLine(body, idx + delim.length, E, code);
160
265
  var parts = [];
266
+ var counted = guard.limits.counter(C.LIMITS.MIME_MAX_PARTS, _factory(E), code, "the multipart body part");
161
267
  while (true) {
268
+ counted.tick();
162
269
  var next = _findDelim(body, delim, pos);
163
270
  if (next < 0) throw new E(code, "an unterminated multipart body part (no closing boundary)");
164
271
  var partEnd = next;
package/lib/ocsp.js CHANGED
@@ -350,7 +350,7 @@ function _sign(responseData, responder, opts) {
350
350
  opts = guard.identifier.optionsObject(opts, _err, "ocsp/bad-input", "pki.ocsp.sign options");
351
351
  guard.identifier.assertKnownKeys(opts, _SIGN_OPTS, _err, "ocsp/bad-input",
352
352
  "pki.ocsp.sign has an unknown option (the nonce to echo back is `nonce`): ");
353
- responseData = responseData || {};
353
+ responseData = responseData || _ocspIntrinsic.create(null);
354
354
  if (typeof responseData !== "object") throw _err("ocsp/bad-input", "the responseData must be an object { responderID, responses, producedAt? }");
355
355
  guard.identifier.assertKnownKeys(responseData, _RESPONSE_DATA_KEYS, _err, "ocsp/bad-input", "unknown responseData field (accepted: responderID, responses, producedAt): ");
356
356
  if (!responder || typeof responder !== "object") throw _err("ocsp/bad-input", "a responder must be { cert, key }");
@@ -449,7 +449,7 @@ function _responderID(rid, respCert) {
449
449
  throw _err("ocsp/bad-input", "responderID must be \"byName\" or \"byKey\"");
450
450
  }
451
451
  function _buildSingleResponse(r, opts) {
452
- r = r || {};
452
+ r = r || _ocspIntrinsic.create(null);
453
453
  var certIdP;
454
454
  if (typeof r !== "object") return _promiseReject(_Promise, _err("ocsp/bad-input", "each response entry must be an object"));
455
455
  try { guard.identifier.assertKnownKeys(r, _SINGLE_RESPONSE_KEYS, _err, "ocsp/bad-input", "unknown response entry field (accepted: cert, issuer, certID, hashAlgorithm, status, thisUpdate, nextUpdate, singleExtensions): "); }
@@ -1867,7 +1867,7 @@ async function _validate(path, opts, run, scope) {
1867
1867
  }
1868
1868
 
1869
1869
  if (opts.ctLogList != null) {
1870
- var ctCheck = await ctGateCheck(certs[n - 1], certs, anchor, opts.ctLogList, opts.ctPolicy || {}, n, opts.time);
1870
+ var ctCheck = await ctGateCheck(certs[n - 1], certs, anchor, opts.ctLogList, opts.ctPolicy || intrinsic.create(null), n, opts.time);
1871
1871
  var target = null;
1872
1872
  for (var tr = 0; tr < state.results.length; tr++) { if (state.results[tr].index === n - 1) { target = state.results[tr]; break; } }
1873
1873
  if (target) guard.list.append(target.checks, ctCheck);
@@ -2599,7 +2599,7 @@ function _ocspFromBytes(response) {
2599
2599
  }
2600
2600
 
2601
2601
  function _verifyOcspParsed(parsedResponse, cert, issuerCert, time, opts) {
2602
- opts = opts || {};
2602
+ opts = opts || intrinsic.create(null);
2603
2603
  /** @internal The captured finite test rather than a live `isNaN`: a valid Date's instant is always
2604
2604
  * finite and an invalid one's is not, so the two answer the same question, and the instant is read
2605
2605
  * ONCE into the value the test decides on. */
@@ -3356,7 +3356,7 @@ async function _aiaFetchOne(uri, aia) {
3356
3356
  var res = await guard.async.invoked(aia.transport,
3357
3357
  [{ method: "GET", url: uri, tls: aia.tls, timeout: aia.timeout, maxResponseBytes: aia.maxResponseBytes, blockPrivateAddresses: true }],
3358
3358
  E, "path/bad-input", "opts.transport");
3359
- res = res || {};
3359
+ res = res || intrinsic.create(null);
3360
3360
  if (res.status !== 200) throw E("path/aia-status", "an AIA fetch returned HTTP " + res.status + " (only 200 is a cert source; no redirect following)");
3361
3361
  var body = guard.bytes.isByteSource(res.body)
3362
3362
  ? guard.bytes.source(res.body, PathError, "path/aia-bad-body", "the AIA response body")
package/lib/pbes2.js CHANGED
@@ -4,6 +4,9 @@
4
4
  // @internal
5
5
 
6
6
  var asn1 = require("./asn1-der");
7
+ /** @internal The record constructor, captured at load, for the reason the same capture in
8
+ * `lib/inspect.js` gives: arming this module counts 25 live runtime reads. */
9
+ var _create = Object.create;
7
10
  var oid = require("./oid");
8
11
  var webcrypto = require("./webcrypto");
9
12
  var guard = require("./guard-all");
@@ -110,7 +113,7 @@ function cbcDecrypt(key, iv, ct, keyBits, E, code) {
110
113
  }
111
114
 
112
115
  function pbes2Encrypt(pwBytes, plaintext, opts, E, prefix) {
113
- opts = opts || {};
116
+ opts = opts || _create(null);
114
117
  var cipherName = opts.cipher || "aes256-CBC";
115
118
  var keyBits = CONTENT_KEYBITS[O(cipherName)];
116
119
  if (!keyBits || cipherName.indexOf("CBC") === -1) throw E(prefix + "/bad-input", "unsupported PBES2 cipher " + cipherName + " (AES-CBC only)");
@@ -168,9 +171,10 @@ function pbmac1AlgId(desc) {
168
171
 
169
172
  function pbmac1(pwBytes, salt, iterationCount, keyLength, prfHash, macHash, message) {
170
173
  var subtle = webcrypto.webcrypto.subtle;
171
- /** @internal Every step is continued through the capture, and the wipe is attached on BOTH outcomes
172
- * rather than through `finally`, which calls the receiver's own `then`. These steps derive the key
173
- * a PBMAC1 integrity tag is computed under, so a replacement settling one hands back a tag computed
174
+ /** @internal Every step is continued through the capture, and the wipe is attached on the success
175
+ * outcome and the failure outcome separately, not through `finally`, which calls the receiver's own
176
+ * `then`. These steps derive the key a PBMAC1 integrity tag is computed under, so a replacement
177
+ * settling one hands back a tag computed
174
178
  * under bytes nobody derived, and skips the wipe that keeps the derived key from outliving it. */
175
179
  var base = guard.async.chain(subtle.importKey("raw", pwBytes, { name: "PBKDF2" }, false, ["deriveBits"]),
176
180
  function (baseKey) {
@@ -237,7 +237,7 @@ function _buildBag(bag, opts, depth) {
237
237
  case "shroudedKey": {
238
238
  var kDer = _coerceDer(bag.key, "shroudedKey key");
239
239
  try { pkcs8.parse(kDer); } catch (e2) { throw _err("pkcs12/bad-input", "shroudedKey key is not a well-formed PKCS#8 PrivateKeyInfo", e2); }
240
- var enc = bag.encrypt || {};
240
+ var enc = bag.encrypt || intrinsic.create(null);
241
241
  var bagPbe = _pbeOpts(enc);
242
242
  var pw = _pbePasswordOwned(enc.password != null ? enc.password : opts.password);
243
243
  var r;
@@ -552,7 +552,7 @@ function build(spec, opts) {
552
552
  }
553
553
 
554
554
  async function _build(spec, opts) {
555
- opts = opts || {};
555
+ opts = opts || intrinsic.create(null);
556
556
  var form = _specForm(spec);
557
557
  if (form.isObject) {
558
558
  guard.identifier.assertKnownKeys(spec, form.full ? _BUILD_SPEC_FULL_KEYS : _BUILD_SPEC_SHORTHAND_KEYS,
@@ -621,7 +621,7 @@ async function _build(spec, opts) {
621
621
  : "");
622
622
  });
623
623
  }
624
- if (opts.mac !== false) _push(pfxChildren,await _buildMacData(opts.mac || {}, opts.password, authSafeDer));
624
+ if (opts.mac !== false) _push(pfxChildren,await _buildMacData(opts.mac || intrinsic.create(null), opts.password, authSafeDer));
625
625
  pfx = b.sequence(pfxChildren);
626
626
  }
627
627
 
@@ -676,7 +676,7 @@ async function verifyMac(pfx, password, opts) {
676
676
  }
677
677
 
678
678
  async function _verifyMacOfStore(m, password, opts) {
679
- opts = opts || {};
679
+ opts = opts || intrinsic.create(null);
680
680
  if (m.integrityMode !== "password" || !m.mac) throw _err("pkcs12/bad-input", "the store carries no password MAC (integrityMode " + m.integrityMode + ")");
681
681
  var expected = m.mac.macValue;
682
682
  var computed;
@@ -767,7 +767,7 @@ function _capWork(iterations, salt, opts, keyLength, hardCap) {
767
767
  * var keyDer = store.keys[0].pkcs8, certDer = store.certs[0].cert;
768
768
  */
769
769
  async function open(pfx, password, opts) {
770
- opts = opts || {};
770
+ opts = opts || intrinsic.create(null);
771
771
  guard.identifier.assertKnownKeys(opts, _OPEN_OPTS, _err, "pkcs12/bad-input", "pki.pkcs12.open has an unknown option ");
772
772
  /** @internal Every option is taken once, here, and everything below reads the snapshot. A store
773
773
  * is opened in many passes, the MAC and then each bag, so an option left on the caller's object is
package/lib/scep.js CHANGED
@@ -745,7 +745,7 @@ function _drive(method, url, body, headers, opts, transport, budgets) {
745
745
  if (proxySnap != null) req.proxy = proxySnap;
746
746
  if (curBody != null) req.body = curBody;
747
747
  return guard.async.invoked(transport, [req], _err, "scep/bad-input", "opts.transport").then(function (res) {
748
- res = res || {};
748
+ res = res || intrinsic.create(null);
749
749
  var blen = _responseLen(res.body);
750
750
  if (blen > budgets.maxResponseBytes) throw _err("scep/response-too-large", "the response body (" + blen + " bytes) exceeds the " + budgets.maxResponseBytes + "-byte cap");
751
751
  var status = res.status;
@@ -169,7 +169,7 @@ function time(ns) {
169
169
 
170
170
  function field(name, schema) { return { fkind: "required", name: name, schema: schema }; }
171
171
  function optional(name, schema, opts) {
172
- opts = opts || {};
172
+ opts = opts || intrinsic.create(null);
173
173
  var match = opts.whenAny
174
174
  ? function () { return true; }
175
175
  : opts.whenUniversal
@@ -182,51 +182,51 @@ function optional(name, schema, opts) {
182
182
  defaultCode: opts.defaultCode };
183
183
  }
184
184
  function trailing(members, opts) {
185
- opts = opts || {};
185
+ opts = opts || intrinsic.create(null);
186
186
  return { fkind: "trailing", members: members, minTag: opts.minTag, maxTag: opts.maxTag,
187
187
  unexpectedCode: opts.unexpectedCode, orderCode: opts.orderCode };
188
188
  }
189
189
 
190
190
 
191
191
  function seq(fields, opts) {
192
- opts = opts || {};
192
+ opts = opts || intrinsic.create(null);
193
193
  return { kind: "seq", fields: fields, assert: opts.assert || "sequence", implicitTag: opts.implicitTag, arity: opts.arity,
194
194
  code: opts.code, what: opts.what, build: opts.build, checks: opts.checks || [] };
195
195
  }
196
196
 
197
197
  function explicit(tag, schema, opts) {
198
- opts = opts || {};
198
+ opts = opts || intrinsic.create(null);
199
199
  return { kind: "explicit", tag: tag, schema: schema, emptyCode: opts.emptyCode, code: opts.code, what: opts.what };
200
200
  }
201
201
 
202
202
  function choice(alts, opts) {
203
- opts = opts || {};
203
+ opts = opts || intrinsic.create(null);
204
204
  return { kind: "choice", alts: alts, code: opts.code, what: opts.what };
205
205
  }
206
206
 
207
207
  function seqOf(item, opts) {
208
- opts = opts || {};
208
+ opts = opts || intrinsic.create(null);
209
209
  return { kind: "repeat", item: item, assert: opts.assert || "sequence", code: opts.code, what: opts.what,
210
210
  min: opts.min, max: opts.max, maxCode: opts.maxCode,
211
211
  unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
212
212
  }
213
213
  function setOf(item, opts) {
214
- opts = opts || {};
214
+ opts = opts || intrinsic.create(null);
215
215
  return { kind: "repeat", item: item, assert: opts.assert || "set", derSetOrder: true, code: opts.code, what: opts.what,
216
216
  min: opts.min, max: opts.max, maxCode: opts.maxCode,
217
217
  unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
218
218
  }
219
219
  function setOfUnique(item, keyFn, opts) {
220
- return setOf(item, Object.assign({ unique: keyFn }, opts || {}));
220
+ return setOf(item, Object.assign({ unique: keyFn }, opts || intrinsic.create(null)));
221
221
  }
222
222
  function implicitSetOf(tag, item, opts) {
223
- opts = opts || {};
223
+ opts = opts || intrinsic.create(null);
224
224
  return { kind: "repeat", item: item, assert: "implicit", implicitTag: tag, derSetOrder: true, code: opts.code, what: opts.what,
225
225
  min: opts.min, max: opts.max, maxCode: opts.maxCode,
226
226
  unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
227
227
  }
228
228
  function implicitSeqOf(tag, item, opts) {
229
- opts = opts || {};
229
+ opts = opts || intrinsic.create(null);
230
230
  return { kind: "repeat", item: item, assert: "implicit", implicitTag: tag, code: opts.code, what: opts.what,
231
231
  min: opts.min, max: opts.max, maxCode: opts.maxCode,
232
232
  unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
@@ -471,7 +471,7 @@ function _wrapConstructed(schema, parts) {
471
471
  function _present(v) { return v !== undefined && v !== null; }
472
472
 
473
473
  function _encodeSeq(schema, value, ctx) {
474
- value = value || {};
474
+ value = value || intrinsic.create(null);
475
475
  var parts = [];
476
476
  for (var f = 0; f < schema.fields.length; f++) {
477
477
  var fld = schema.fields[f];
@@ -578,7 +578,7 @@ function _encodeChoice(schema, value, ctx) {
578
578
  * { code: "app/bad-der", what: "the embedded structure" });
579
579
  */
580
580
  function embeddedDer(schema, bytes, ctx, opts) {
581
- opts = opts || {};
581
+ opts = opts || intrinsic.create(null);
582
582
  if (opts.budget) {
583
583
  if (!(opts.budget.remaining > 0)) {
584
584
  throw ctx.E(opts.budgetCode || opts.code, (opts.what || "embedded DER") +
@@ -330,7 +330,7 @@ function _blockCap(given, ceiling, what, PemError) {
330
330
  * label is the only thing separating a CERTIFICATE from a TRUSTED CERTIFICATE or a PRIVATE KEY, and
331
331
  * the byte offset it started at, so a fault in a file of hundreds names the one object it is about. */
332
332
  function pemDecodeBundle(text, opts, PemError, detect) {
333
- opts = opts || {};
333
+ opts = opts || _create(null);
334
334
  var maxBlocks = _blockCap(opts.maxBlocks, constants.LIMITS.PEM_MAX_BLOCKS, "maxBlocks", PemError);
335
335
  var maxDecoded = _blockCap(opts.maxDecodedBytes, constants.LIMITS.PEM_MAX_DECODED_BYTES, "maxDecodedBytes", PemError);
336
336
  var route = opts.route === true;
@@ -739,7 +739,7 @@ function versionReader(ns, accept) {
739
739
  }
740
740
 
741
741
  function algorithmIdentifier(ns, opts) {
742
- opts = opts || {};
742
+ opts = opts || _create(null);
743
743
  return schema.seq([
744
744
  schema.field("algorithm", schema.oidLeaf()),
745
745
  schema.optional("parameters", schema.any(), { whenAny: true }),
@@ -761,7 +761,7 @@ function algorithmIdentifier(ns, opts) {
761
761
  * (RFC 5652 sec. 10.2.4). CMS names the type and RFC 9763 sec. 3.1 reuses it inside a CSR attribute,
762
762
  * so the shape is defined once and each caller supplies its own code and name for the refusal. */
763
763
  function issuerAndSerialNumber(ns, opts) {
764
- opts = opts || {};
764
+ opts = opts || _create(null);
765
765
  return schema.seq([
766
766
  schema.field("issuer", name(ns)),
767
767
  schema.field("serialNumber", schema.integerLeaf()),
@@ -952,7 +952,7 @@ function relativeDistinguishedName(ns) {
952
952
  return schema.setOf(attributeTypeAndValue(ns), { assert: "set", min: 1, code: ns.prefix + "/bad-rdn", what: "RelativeDistinguishedName" });
953
953
  }
954
954
  function name(ns, opts) {
955
- opts = opts || {};
955
+ opts = opts || _create(null);
956
956
  function nameBuild(m) {
957
957
  var rdns = [], parts = [];
958
958
  _forEach(m.items, function (rdnItem) {
@@ -978,7 +978,7 @@ function name(ns, opts) {
978
978
  }
979
979
 
980
980
  function generalizedTime(ns, opts) {
981
- opts = opts || {};
981
+ opts = opts || _create(null);
982
982
  var code = opts.code || (ns.prefix + "/bad-time");
983
983
  var message = opts.message || "the time must be a GeneralizedTime";
984
984
  var readOpts = opts.allowFractional ? { allowFractional: true } : undefined;
@@ -991,7 +991,7 @@ function generalizedTime(ns, opts) {
991
991
  }
992
992
 
993
993
  function utf8Text(ns, opts) {
994
- opts = opts || {};
994
+ opts = opts || _create(null);
995
995
  var code = opts.code || (ns.prefix + "/bad-freetext");
996
996
  var message = opts.message || "the element must be a UTF8String";
997
997
  return schema.decode(function (n, ctx) {
@@ -1003,7 +1003,7 @@ function utf8Text(ns, opts) {
1003
1003
  }
1004
1004
 
1005
1005
  function rawNonEmptySequence(ns, opts) {
1006
- opts = opts || {};
1006
+ opts = opts || _create(null);
1007
1007
  var code = opts.code || (ns.prefix + "/bad-sequence");
1008
1008
  var message = opts.message || "expected a non-empty universal SEQUENCE";
1009
1009
  return schema.decode(function (n, ctx) {
@@ -1069,7 +1069,7 @@ var GN_IA5 = _assign(_create(null), { 1: 1, 2: 1, 6: 1 });
1069
1069
  var DIRECTORY_STRING_TAGS = [asn1.TAGS.UTF8_STRING, asn1.TAGS.PRINTABLE_STRING, asn1.TAGS.TELETEX_STRING,
1070
1070
  asn1.TAGS.UNIVERSAL_STRING, asn1.TAGS.BMP_STRING];
1071
1071
  function generalName(ns, opts) {
1072
- opts = opts || {};
1072
+ opts = opts || _create(null);
1073
1073
  var code = opts.code || (ns.prefix + "/bad-general-name");
1074
1074
  var decodeValue = opts.decodeValue === true;
1075
1075
  var subtreeBase = opts.subtreeBase === true;
@@ -1165,7 +1165,7 @@ function generalName(ns, opts) {
1165
1165
  }
1166
1166
 
1167
1167
  function generalNames(ns, opts) {
1168
- opts = opts || {};
1168
+ opts = opts || _create(null);
1169
1169
  var code = opts.code || (ns.prefix + "/bad-general-names");
1170
1170
  var gn = generalName(ns, { code: code, decodeValue: opts.decodeValue === true, subtreeBase: opts.subtreeBase === true });
1171
1171
  function build(m) { return { names: _map(m.items, function (it) { return it.value; }), bytes: m.node.bytes }; }
@@ -2528,7 +2528,7 @@ function extension(ns) {
2528
2528
  });
2529
2529
  }
2530
2530
  function extensions(ns, opts) {
2531
- opts = opts || {};
2531
+ opts = opts || _create(null);
2532
2532
  var EXT = extension(ns);
2533
2533
  var extOpts = {
2534
2534
  min: 1, code: ns.prefix + "/bad-extensions", what: "Extensions",
@@ -2540,7 +2540,7 @@ function extensions(ns, opts) {
2540
2540
  }
2541
2541
 
2542
2542
  function spki(ns, opts) {
2543
- opts = opts || {};
2543
+ opts = opts || _create(null);
2544
2544
  return schema.seq([
2545
2545
  schema.field("algorithm", algorithmIdentifier(ns)),
2546
2546
  schema.field("subjectPublicKey", schema.bitString()),
@@ -2558,7 +2558,7 @@ function spki(ns, opts) {
2558
2558
  }
2559
2559
 
2560
2560
  function attribute(ns, opts) {
2561
- opts = opts || {};
2561
+ opts = opts || _create(null);
2562
2562
  var minValues = opts.minValues === undefined ? 1 : opts.minValues;
2563
2563
  return schema.seq([
2564
2564
  schema.field("type", schema.oidLeaf()),
@@ -124,7 +124,7 @@ function resolveSignScheme(cert, so, noSignedAttrs, E) {
124
124
  }
125
125
 
126
126
  function _resolveSignScheme(cert, so, noSignedAttrs, E) {
127
- so = so || {};
127
+ so = so || intrinsic.create(null);
128
128
  var alg = cert.subjectPublicKeyInfo.algorithm;
129
129
  var keyOid = alg.oid;
130
130
  var comp = compositeSig.COMPOSITE_ALGS[keyOid];
@@ -180,7 +180,7 @@ function _resolveSignScheme(cert, so, noSignedAttrs, E) {
180
180
  }
181
181
 
182
182
  function _assertKeyMatchesScheme(key, imp, E, what) {
183
- var ka = key.algorithm || {};
183
+ var ka = key.algorithm || intrinsic.create(null);
184
184
  var subject = what || "CryptoKey";
185
185
  if (_toUpperCase(_String(ka.name)) !== _toUpperCase(_String(imp.name))) {
186
186
  var hint = (_toUpperCase(_String(ka.name)) === "RSA-PSS" && _toUpperCase(_String(imp.name)) === "RSASSA-PKCS1-V1_5")
package/lib/sigstore.js CHANGED
@@ -1715,7 +1715,7 @@ async function verifyBundle(bundle, opts) {
1715
1715
  if (bundle === null || typeof bundle !== "object" && typeof bundle !== "string" && !_isBuffer(bundle)) {
1716
1716
  throw new TypeError("verifyBundle: bundle must be an object, JSON string, or Buffer");
1717
1717
  }
1718
- opts = opts || {};
1718
+ opts = opts || _create(null);
1719
1719
  guard.identifier.assertKnownKeys(opts, _VERIFY_BUNDLE_OPTS, _err, "sigstore/bad-input", "pki.sigstore.verifyBundle has an unknown option ");
1720
1720
  /** @internal parseBundle takes the copy, so every check below runs on plain data that cannot change
1721
1721
  * under it, whichever field it reads and however many times. */