@blamejs/pki 0.8.54 → 0.8.56
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.
- package/CHANGELOG.md +84 -0
- package/lib/acme.js +2 -2
- package/lib/asn1-der.js +17 -5
- package/lib/attrcert-verify.js +1 -1
- package/lib/cmc-verify.js +1 -1
- package/lib/cmp-session.js +2 -2
- package/lib/cmp-verify.js +2 -2
- package/lib/cms-decrypt.js +4 -1
- package/lib/cms-encrypt.js +4 -1
- package/lib/cms-sign.js +26 -12
- package/lib/cms-verify.js +1 -1
- package/lib/composite-kem.js +30 -12
- package/lib/composite-sig.js +42 -23
- package/lib/constants.js +7 -2
- package/lib/crl-verify.js +1 -1
- package/lib/crmf-sign.js +72 -43
- package/lib/crmf-verify.js +1 -1
- package/lib/csr-verify.js +1 -1
- package/lib/ct.js +11 -13
- package/lib/edwards-point.js +1 -1
- package/lib/est.js +3 -3
- package/lib/guard-async.js +22 -1
- package/lib/guard-bytes.js +6 -3
- package/lib/guard-identifier.js +24 -1
- package/lib/guard-intrinsic.js +474 -0
- package/lib/http-digest.js +146 -62
- package/lib/http-transport.js +82 -17
- package/lib/identity-match.js +2 -2
- package/lib/merkle.js +2 -2
- package/lib/ocsp-request-verify.js +1 -1
- package/lib/ocsp.js +46 -22
- package/lib/path-validate.js +234 -88
- package/lib/pbes2.js +14 -7
- package/lib/schema-attrcert.js +2 -2
- package/lib/schema-cmc.js +2 -2
- package/lib/schema-cmp.js +2 -2
- package/lib/schema-cms.js +2 -2
- package/lib/schema-crmf.js +2 -2
- package/lib/schema-csr.js +2 -2
- package/lib/schema-pkix.js +3 -3
- package/lib/schema-x509.js +2 -2
- package/lib/sigstore.js +14 -3
- package/lib/tlog.js +7 -4
- package/lib/trust.js +187 -104
- package/lib/tsp-sign.js +1 -1
- package/lib/webauthn-mds.js +257 -121
- package/lib/webauthn.js +327 -164
- package/lib/webcrypto.js +10 -3
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/guard-intrinsic.js
CHANGED
|
@@ -20,6 +20,15 @@ var _bufferByteLength = Buffer.byteLength;
|
|
|
20
20
|
var _bufferCompare = Buffer.compare;
|
|
21
21
|
var _bufferEquals = uncurry(Buffer.prototype.equals);
|
|
22
22
|
var _bufferToString = uncurry(Buffer.prototype.toString);
|
|
23
|
+
/** @internal The big-endian integer readers, captured at load. A length or a counter read out of a
|
|
24
|
+
* wire structure is what the bounds check and the slice after it are computed from, so a replaced
|
|
25
|
+
* reader decides which bytes a check runs over and which value a monotonicity rule compares. */
|
|
26
|
+
var _readUInt8 = uncurry(Buffer.prototype.readUInt8);
|
|
27
|
+
var _readUInt16BE = uncurry(Buffer.prototype.readUInt16BE);
|
|
28
|
+
var _readUInt32BE = uncurry(Buffer.prototype.readUInt32BE);
|
|
29
|
+
var _readUIntBE = uncurry(Buffer.prototype.readUIntBE);
|
|
30
|
+
var _writeUInt16BE = uncurry(Buffer.prototype.writeUInt16BE);
|
|
31
|
+
var _writeUInt32BE = uncurry(Buffer.prototype.writeUInt32BE);
|
|
23
32
|
/** @internal Key identity, taken off the KeyObject prototype at load. A caller that replaced this
|
|
24
33
|
* method could make two different keys answer as one, which is the question a proof of possession
|
|
25
34
|
* turns on. */
|
|
@@ -40,6 +49,7 @@ var _objectKeys = Object.keys;
|
|
|
40
49
|
var _objectAssign = Object.assign;
|
|
41
50
|
var _objectFreeze = Object.freeze;
|
|
42
51
|
var _isExtensible = Object.isExtensible;
|
|
52
|
+
var _isFrozen = Object.isFrozen;
|
|
43
53
|
var _ownKeys = Reflect.ownKeys;
|
|
44
54
|
var _jsonStringify = JSON.stringify;
|
|
45
55
|
var _mathFloor = Math.floor;
|
|
@@ -68,6 +78,142 @@ var _promiseAny = Promise.any;
|
|
|
68
78
|
* present on the supported runtime floor. */
|
|
69
79
|
var _promiseTry = Promise["try"];
|
|
70
80
|
var _promiseWithResolvers = Promise.withResolvers;
|
|
81
|
+
/** @internal The continuation itself, which the static methods above do not cover: every `p.then(f)`
|
|
82
|
+
* reads `then` off the promise at the call, and the value a continuation RESOLVES is the verdict its
|
|
83
|
+
* caller goes on to report. A replacement that settles `true` without running `f` skips whatever `f`
|
|
84
|
+
* was going to check: in the fold that walks a metadata BLOB's candidate anchors, that feeds `true`
|
|
85
|
+
* into the seed and the chain validation is never called, so a chain unrelated to every supplied
|
|
86
|
+
* root reports trusted. `chain(p, onOk, onFail)` calls the captured method on `p`. */
|
|
87
|
+
var _promiseProto = Promise.prototype;
|
|
88
|
+
var _promiseThen = uncurry(Promise.prototype.then);
|
|
89
|
+
/** @internal Three replaceable mechanisms stand between a captured `then` and the value a caller
|
|
90
|
+
* reads, and closing only the first leaves the verdict steerable:
|
|
91
|
+
*
|
|
92
|
+
* THE METHOD. `p.then(f)` reads `then` off the promise at the call. Measured: a replacement that
|
|
93
|
+
* settled without running `f` made `pki.webauthn.verify` return a packed self-attestation whose
|
|
94
|
+
* signature does not verify, and made `verifyMetadataBlob` hand back a verified catalogue for a
|
|
95
|
+
* chain reaching none of the supplied roots.
|
|
96
|
+
*
|
|
97
|
+
* THE CONSTRUCTION. Native `then` builds the promise it RETURNS through `SpeciesConstructor`, which
|
|
98
|
+
* reads `constructor` off the promise and `Symbol.species` off that, and the species descriptor is
|
|
99
|
+
* configurable. Measured: a species whose executor dropped its resolve function and answered with
|
|
100
|
+
* `Promise.resolve({ valid: true })` made `verifyAssertion` FULFILL with that object where it
|
|
101
|
+
* rejects with `webauthn/bad-input`. So the promise handed back is built here, from the captured
|
|
102
|
+
* constructor, and whatever `then` returns is discarded.
|
|
103
|
+
*
|
|
104
|
+
* THE ADOPTION. Resolving a promise with a thenable is specified to read `then` off that thenable
|
|
105
|
+
* and call it, which is the live method again: a callback returning the verify promise was adopted
|
|
106
|
+
* that way, and a replacement answered the outer chain with a fabricated verdict. A returned real
|
|
107
|
+
* promise is adopted here through the capture instead. A value that is not a promise still goes to
|
|
108
|
+
* the resolve function, because a caller's own thenable IS the thing to call.
|
|
109
|
+
*
|
|
110
|
+
* What remains is the caller's own `await` of the returned promise, which the language resolves by
|
|
111
|
+
* reading `then`. By then every check has run and any refusal has already thrown. */
|
|
112
|
+
// @enforced-by behavioral -- RED vectors replace the method, the species and the adoption in turn
|
|
113
|
+
function chain(p, onOk, onFail) {
|
|
114
|
+
var resolveFn, rejectFn;
|
|
115
|
+
var out = new _Promise(function (res, rej) { resolveFn = res; rejectFn = rej; });
|
|
116
|
+
_chainAttach(p, function (value) {
|
|
117
|
+
if (typeof onOk !== "function") { _chainResolve(out, resolveFn, rejectFn, value); return; }
|
|
118
|
+
var r;
|
|
119
|
+
try { r = onOk(value); }
|
|
120
|
+
catch (e) { rejectFn(e); return; }
|
|
121
|
+
_chainResolve(out, resolveFn, rejectFn, r);
|
|
122
|
+
}, function (reason) {
|
|
123
|
+
if (typeof onFail !== "function") { rejectFn(reason); return; }
|
|
124
|
+
var r;
|
|
125
|
+
try { r = onFail(reason); }
|
|
126
|
+
catch (e) { rejectFn(e); return; }
|
|
127
|
+
_chainResolve(out, resolveFn, rejectFn, r);
|
|
128
|
+
}, rejectFn);
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
131
|
+
/** @internal Is this a promise, decided against the prototype captured at load rather than through
|
|
132
|
+
* `instanceof`, whose `Promise.prototype` read is replaceable, or a brand string, which is
|
|
133
|
+
* configurable per object. A subclass instance has the captured prototype in its chain and is
|
|
134
|
+
* recognized; anything else is a caller's own thenable or a plain value. */
|
|
135
|
+
function _isPromiseBrand(value) {
|
|
136
|
+
var proto = value;
|
|
137
|
+
for (var depth = 0; depth < 64; depth++) {
|
|
138
|
+
proto = _getPrototypeOf(proto);
|
|
139
|
+
if (proto === null) return false;
|
|
140
|
+
if (proto === _promiseProto) return true;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
/** @internal Register the two handlers on whatever the caller supplied. A promise is subscribed to
|
|
145
|
+
* through the capture; a thenable has its own `then` called, which is what a caller supplying one
|
|
146
|
+
* means; anything else is the TypeError `p.then(...)` raises for the same input. A throw from the
|
|
147
|
+
* capture is a REFUSAL rather than a reason to fall back: native `then` reads `constructor` off the
|
|
148
|
+
* promise for its species, so a throwing `constructor` getter is the one way a real promise makes
|
|
149
|
+
* the captured call fail, and falling back to the resolve function there would adopt the promise's
|
|
150
|
+
* own `then` instead, which is the substitution this exists to prevent. */
|
|
151
|
+
function _chainAttach(p, onFulfilled, onRejected, rejectFn) {
|
|
152
|
+
if (p !== null && (typeof p === "object" || typeof p === "function")) {
|
|
153
|
+
if (_isPromiseBrand(p)) {
|
|
154
|
+
try { _promiseThen(p, onFulfilled, onRejected); }
|
|
155
|
+
catch (e) { rejectFn(e); }
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
var thenFn;
|
|
159
|
+
try { thenFn = p.then; }
|
|
160
|
+
catch (e) { rejectFn(e); return; }
|
|
161
|
+
if (typeof thenFn === "function") { _chainThenable(p, thenFn, onFulfilled, onRejected); return; }
|
|
162
|
+
}
|
|
163
|
+
throw new TypeError("intrinsic.chain: the first argument must be a promise or a thenable");
|
|
164
|
+
}
|
|
165
|
+
/** @internal The thenable job for a RECEIVER that is not a promise, which is what `p.then(f)` does
|
|
166
|
+
* for the same argument: it calls the object's own `then`. First settlement wins and a throw after
|
|
167
|
+
* one is dropped, as the specified job does. */
|
|
168
|
+
function _chainThenable(value, thenFn, onFulfilled, onRejected) {
|
|
169
|
+
var settled = false;
|
|
170
|
+
try {
|
|
171
|
+
_reflectApply(thenFn, value, [
|
|
172
|
+
function (v) { if (!settled) { settled = true; onFulfilled(v); } },
|
|
173
|
+
function (e) { if (!settled) { settled = true; onRejected(e); } },
|
|
174
|
+
]);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
if (!settled) { settled = true; onRejected(e); }
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function _chainResolve(out, resolveFn, rejectFn, value) {
|
|
180
|
+
/** @internal A handler returning the promise this call hands back is the cycle the native
|
|
181
|
+
* resolution procedure rejects rather than waiting on. Subscribing to it would wait forever, and
|
|
182
|
+
* a verify that never settles is a verify that never refuses. */
|
|
183
|
+
if (value === out) {
|
|
184
|
+
rejectFn(new TypeError("intrinsic.chain: a handler returned the promise it settles"));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
/** @internal A promise is adopted through the capture, and its own value goes through this step
|
|
188
|
+
* again. Anything else is handed to the resolve function, which reads `then` ONCE and calls it if
|
|
189
|
+
* it is callable: that is the specified procedure, and testing `then` here first would read it
|
|
190
|
+
* twice, so a getter answering a non-function and then a function would be settled by the second
|
|
191
|
+
* read after the first had decided. No route in this toolkit returns a thenable that is not a
|
|
192
|
+
* promise, and the resolve function calling a caller's own `then` is what a caller supplying one
|
|
193
|
+
* means. */
|
|
194
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
195
|
+
/** @internal The brand test runs inside the refusal too. This function is called from inside a
|
|
196
|
+
* continuation, so a throw escaping it settles nothing and the chain waits forever: a proxy
|
|
197
|
+
* whose `getPrototypeOf` trap throws left the verb pending with an unhandled rejection beside
|
|
198
|
+
* it. Anything that cannot be classified is refused instead. */
|
|
199
|
+
var isPromise;
|
|
200
|
+
try { isPromise = _isPromiseBrand(value); }
|
|
201
|
+
catch (e) { rejectFn(e); return; }
|
|
202
|
+
if (!isPromise) { resolveFn(value); return; }
|
|
203
|
+
try {
|
|
204
|
+
_promiseThen(value, function (v) { _chainResolve(out, resolveFn, rejectFn, v); }, rejectFn);
|
|
205
|
+
} catch (e) {
|
|
206
|
+
/** @internal A refusal, not a fallback. Two kinds of value reach here: one carrying the promise
|
|
207
|
+
* prototype without a promise's state, and a real promise whose species cannot be used, which
|
|
208
|
+
* is a `constructor` getter that throws or one answering something that is not a constructor.
|
|
209
|
+
* Settling through the resolve function instead would adopt the value's own `then`, which is
|
|
210
|
+
* the substitution the capture exists to prevent, so neither is passed along. */
|
|
211
|
+
rejectFn(e);
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
resolveFn(value);
|
|
216
|
+
}
|
|
71
217
|
/** @internal The URL parser, captured for the reason the promise constructor is: what it returns names
|
|
72
218
|
* the host a request is sent to. A replacement installed while a call is in flight answers with a
|
|
73
219
|
* genuine URL of its own, and an endpoint built from that answer reaches a host the caller never
|
|
@@ -102,6 +248,279 @@ var _arrFilter = uncurry(Array.prototype.filter);
|
|
|
102
248
|
var _arrEvery = uncurry(Array.prototype.every);
|
|
103
249
|
var _arrSome = uncurry(Array.prototype.some);
|
|
104
250
|
var _arrIndexOf = uncurry(Array.prototype.indexOf);
|
|
251
|
+
/** @internal The fold, captured at load. A fold is how a sequence of checks is chained into one verdict,
|
|
252
|
+
* so a replacement that returns its seed without visiting an element answers for a sequence it never
|
|
253
|
+
* walked. */
|
|
254
|
+
var _arrReduce = uncurry(Array.prototype.reduce);
|
|
255
|
+
/** @internal The append these three build with. `push` is not usable for it: it writes through Set,
|
|
256
|
+
* which WALKS THE PROTOTYPE for a numeric setter, so an accessor installed at `Array.prototype[0]`
|
|
257
|
+
* takes the value and leaves no own property on the array at all, and the index then reads back as
|
|
258
|
+
* whatever its getter answers. MEASURED: a fresh literal appended to with `push` held no own index
|
|
259
|
+
* `0` and read as the getter's value. `defineProperty` consults no setter, which is the same reason
|
|
260
|
+
* `guard.list.append` is written this way. */
|
|
261
|
+
function _appendOwn(out, i, value) {
|
|
262
|
+
_defineProperty(out, i, { value: value, writable: true, enumerable: true, configurable: true });
|
|
263
|
+
}
|
|
264
|
+
var _strCharCodeAt = uncurry(String.prototype.charCodeAt);
|
|
265
|
+
var _strSliceOwn = uncurry(String.prototype.slice);
|
|
266
|
+
/** @internal A split on ONE delimiter character, scanned rather than dispatched.
|
|
267
|
+
* `String.prototype.split` is specified to look the separator's `Symbol.split` method up and call
|
|
268
|
+
* it (ES2015 21.1.3.19 step 2), so the separator's prototype chain is part of the operation and a
|
|
269
|
+
* capture of `split` does not close it. Hard rule 11 bans `split` in `lib/` for exactly that
|
|
270
|
+
* reason. MEASURED on Node 24.21, the supported runtime: a captured split with a string separator
|
|
271
|
+
* DOES dispatch to an installed `String.prototype[Symbol.split]`, and that made
|
|
272
|
+
* `isBlockedIp("127.0.0.1")` answer false, so a request to loopback proceeded under
|
|
273
|
+
* `blockPrivateAddresses`. Node 26.9 fast-paths a primitive-string separator past the lookup, which
|
|
274
|
+
* is why a local run cannot see it: whether the dispatch happens is a property of the engine.
|
|
275
|
+
* `charCodeAt` and `slice` carry no such protocol, and the delimiter here is a CHARACTER CODE
|
|
276
|
+
* rather than a string, so there is no separator object to consult on any engine. */
|
|
277
|
+
// @enforced-by behavioral -- a RED vector on Node 24 pins isBlockedIp against an installed @@split
|
|
278
|
+
function splitChar(s, code) {
|
|
279
|
+
/** @internal The receiver has to BE a string. `charCodeAt` and `slice` each convert their receiver,
|
|
280
|
+
* so an object answering `toString` differently per call is scanned as one value and sliced as
|
|
281
|
+
* another: measured, a receiver reporting length 3 returned the fields of a string the delimiter
|
|
282
|
+
* scan never saw. The delimiter has to be a number for the same reason in reverse. `===` against
|
|
283
|
+
* a character code never coerces, so an object delimiter matches nothing and the whole input comes
|
|
284
|
+
* back as a single field, which reads as "this value carries no delimiter" at every caller. */
|
|
285
|
+
if (typeof s !== "string") {
|
|
286
|
+
throw new TypeError("intrinsic.splitChar: the receiver must be a string");
|
|
287
|
+
}
|
|
288
|
+
if (typeof code !== "number" || !_isSafeInteger(code)) {
|
|
289
|
+
throw new TypeError("intrinsic.splitChar: the delimiter must be a character code");
|
|
290
|
+
}
|
|
291
|
+
var out = [];
|
|
292
|
+
var n = s.length, start = 0, k = 0;
|
|
293
|
+
for (var i = 0; i < n; i++) {
|
|
294
|
+
if (_strCharCodeAt(s, i) === code) { _appendOwn(out, k++, _strSliceOwn(s, start, i)); start = i + 1; }
|
|
295
|
+
}
|
|
296
|
+
_appendOwn(out, k, _strSliceOwn(s, start, n));
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
299
|
+
/** @internal The element count, refusing anything but a real array. An array's `length` is an OWN
|
|
300
|
+
* data property, so reading it consults nothing; an array-LIKE answers from wherever its own
|
|
301
|
+
* descriptor says, and a typed array answers from an accessor on `%TypedArray%.prototype` that a
|
|
302
|
+
* caller can redefine, which would report zero and empty every result below. The four verbs are for
|
|
303
|
+
* lists, so the narrow argument is the honest contract rather than a length read taken on trust;
|
|
304
|
+
* `guard.list.append` refuses a non-array for the same reason. */
|
|
305
|
+
function _ownLength(list, who) {
|
|
306
|
+
if (!_isArray(list)) throw new TypeError("intrinsic." + who + ": the receiver must be an array");
|
|
307
|
+
var n = list.length;
|
|
308
|
+
/** @internal The count is read ONCE and type-checked, because `isArray` is satisfied by a Proxy
|
|
309
|
+
* over an array whose `length` trap returns an OBJECT. Coerced afresh on each comparison, such a
|
|
310
|
+
* length answers 2 and then 1, so a loop reading it per iteration visits fewer elements than the
|
|
311
|
+
* first read promised. MEASURED through `pki.path.validate`: a proxied two-certificate path whose
|
|
312
|
+
* length shrank that way reported `valid: true` with the second certificate silently dropped.
|
|
313
|
+
* `guard.list` validates its count the same way, and for the same reason. */
|
|
314
|
+
if (typeof n !== "number" || !_isSafeInteger(n) || n < 0) {
|
|
315
|
+
throw new TypeError("intrinsic." + who + ": the receiver's length is not a non-negative integer");
|
|
316
|
+
}
|
|
317
|
+
return n;
|
|
318
|
+
}
|
|
319
|
+
/** @internal A caller-supplied index bound, coerced ONCE and held to a whole number. The clamping
|
|
320
|
+
* arithmetic below reads each bound two or three times, and every relational comparison coerces an
|
|
321
|
+
* object afresh: measured, a `start` whose `valueOf` answered 1 three times and then 0 was compared
|
|
322
|
+
* as 1 and sliced from 0, so the window returned was not the window any single read describes. A
|
|
323
|
+
* fractional bound is refused rather than truncated, because reading `list[0.5]` finds no slot and
|
|
324
|
+
* returns a result of the right length filled with nothing, which a caller reads as a window of
|
|
325
|
+
* absent values rather than as the bad argument it is. */
|
|
326
|
+
function _ownBound(value, fallback, who) {
|
|
327
|
+
if (value === undefined) return fallback;
|
|
328
|
+
var n = _Number(value);
|
|
329
|
+
if (!_isSafeInteger(n)) {
|
|
330
|
+
throw new TypeError("intrinsic." + who + ": a bound must be a safe integer");
|
|
331
|
+
}
|
|
332
|
+
return n;
|
|
333
|
+
}
|
|
334
|
+
// @enforced-by behavioral -- a RED vector installs an Array.prototype numeric setter and pins that
|
|
335
|
+
/** @internal The same append, for a module that holds a list and adds to its end. `guard.list.append`
|
|
336
|
+
* is the orchestrated form of this and is preferred where `guard` is in scope; this exists for the
|
|
337
|
+
* modules that take only the intrinsic captures. */
|
|
338
|
+
function append(list, value) {
|
|
339
|
+
_appendOwn(list, _ownLength(list, "append"), value);
|
|
340
|
+
return list;
|
|
341
|
+
}
|
|
342
|
+
/** @internal Membership and a universal test over the OWN elements. `indexOf` and `every` are
|
|
343
|
+
* specified in terms of HasProperty, so both consult the prototype at an index the list has a hole
|
|
344
|
+
* at: `indexOf` finds a value the list does not hold, and `every` SKIPS the hole and so answers
|
|
345
|
+
* true for a list with no elements of its own at all. Together that is an allow-list a caller left
|
|
346
|
+
* empty admitting a value installed on the prototype, which is why these read own indexes and count
|
|
347
|
+
* a hole as a member that fails any test. */
|
|
348
|
+
// @enforced-by behavioral -- a RED vector installs Array.prototype[0] and drives the origin door
|
|
349
|
+
function ownIndexOf(list, value) {
|
|
350
|
+
var n = _ownLength(list, "ownIndexOf");
|
|
351
|
+
for (var i = 0; i < n; i++) {
|
|
352
|
+
if (_getOwnPropertyDescriptor(list, i) !== undefined && _ownAt(list, i) === value) return i;
|
|
353
|
+
}
|
|
354
|
+
return -1;
|
|
355
|
+
}
|
|
356
|
+
/** @internal Every element of a list of promises, awaited together, without consulting an operation
|
|
357
|
+
* a caller can replace. Capturing `Promise.all` is not sufficient: it performs GetPromiseResolve on
|
|
358
|
+
* the constructor at EACH call, so a replaced `Promise.resolve` answering a fulfilled `true` for
|
|
359
|
+
* every input hands the aggregate its own values and never awaits a component. Measured on the
|
|
360
|
+
* composite signature verifier, whose verdict is the conjunction of two component results: a
|
|
361
|
+
* certificate whose classical half is corrupted reported `valid: true`. This subscribes to each
|
|
362
|
+
* member through `chain` and settles its own promise when the last one arrives. */
|
|
363
|
+
// @enforced-by behavioral -- a RED vector replaces Promise.resolve and pins the composite verdict
|
|
364
|
+
function allOf(list) {
|
|
365
|
+
var n = _ownLength(list, "allOf");
|
|
366
|
+
var resolveFn, rejectFn;
|
|
367
|
+
var out = new _Promise(function (res, rej) { resolveFn = res; rejectFn = rej; });
|
|
368
|
+
var results = [];
|
|
369
|
+
var pending = n;
|
|
370
|
+
var settled = false;
|
|
371
|
+
if (n === 0) { resolveFn(_detached(results)); return out; }
|
|
372
|
+
for (var i = 0; i < n; i++) {
|
|
373
|
+
(function (index) {
|
|
374
|
+
chain(_ownAt(list, index), function (value) {
|
|
375
|
+
if (settled) return;
|
|
376
|
+
_appendOwn(results, index, value);
|
|
377
|
+
pending -= 1;
|
|
378
|
+
if (pending === 0) { settled = true; resolveFn(_detached(results)); }
|
|
379
|
+
}, function (reason) {
|
|
380
|
+
if (settled) return;
|
|
381
|
+
settled = true;
|
|
382
|
+
rejectFn(reason);
|
|
383
|
+
});
|
|
384
|
+
})(i);
|
|
385
|
+
}
|
|
386
|
+
return out;
|
|
387
|
+
}
|
|
388
|
+
/** @internal A list with no prototype, which is how an aggregate's result list is handed back.
|
|
389
|
+
* Settling a promise with a value is specified to read `then` off that value and call it when it is
|
|
390
|
+
* callable, so a `then` installed on `Array.prototype` makes every ordinary array a thenable:
|
|
391
|
+
* measured, both aggregates below settled with the string that replacement answered instead of
|
|
392
|
+
* their result list. A list that inherits nothing has no `then` to find. Every consumer reads these
|
|
393
|
+
* through the captured verbs, which take the receiver rather than calling a method on it. */
|
|
394
|
+
function _detached(list) {
|
|
395
|
+
_setPrototypeOf(list, null);
|
|
396
|
+
return list;
|
|
397
|
+
}
|
|
398
|
+
/** @internal The settled outcome of every member, in the shape `Promise.allSettled` reports, built
|
|
399
|
+
* the same way and for the same reason: the static form reads `resolve` off the constructor at each
|
|
400
|
+
* call, so a replacement answers for every member and the outcomes a caller reads are its own. The
|
|
401
|
+
* composite KEM combiner reads both halves of a shared secret out of these records. */
|
|
402
|
+
// @enforced-by behavioral -- a RED vector replaces Promise.resolve and pins the combined secret
|
|
403
|
+
function settledOf(list) {
|
|
404
|
+
var n = _ownLength(list, "settledOf");
|
|
405
|
+
var resolveFn;
|
|
406
|
+
var out = new _Promise(function (res) { resolveFn = res; });
|
|
407
|
+
var records = [];
|
|
408
|
+
var pending = n;
|
|
409
|
+
if (n === 0) { resolveFn(_detached(records)); return out; }
|
|
410
|
+
for (var i = 0; i < n; i++) {
|
|
411
|
+
(function (index) {
|
|
412
|
+
chain(_ownAt(list, index), function (value) {
|
|
413
|
+
_appendOwn(records, index, { status: "fulfilled", value: value });
|
|
414
|
+
pending -= 1;
|
|
415
|
+
if (pending === 0) resolveFn(_detached(records));
|
|
416
|
+
}, function (reason) {
|
|
417
|
+
_appendOwn(records, index, { status: "rejected", reason: reason });
|
|
418
|
+
pending -= 1;
|
|
419
|
+
if (pending === 0) resolveFn(_detached(records));
|
|
420
|
+
});
|
|
421
|
+
})(i);
|
|
422
|
+
}
|
|
423
|
+
return out;
|
|
424
|
+
}
|
|
425
|
+
// @enforced-by behavioral -- the same RED vector pins the universal form
|
|
426
|
+
function everyOwn(list, pred) {
|
|
427
|
+
var n = _ownLength(list, "everyOwn");
|
|
428
|
+
for (var i = 0; i < n; i++) {
|
|
429
|
+
var d = _getOwnPropertyDescriptor(list, i);
|
|
430
|
+
if (d === undefined) return false;
|
|
431
|
+
if (!pred(_hasOwn(d, "value") ? d.value : (typeof d.get === "function" ? _reflectApply(d.get, list, []) : undefined), i, list)) return false;
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
/** @internal A selection and a projection that consult NO construction protocol. Capturing
|
|
436
|
+
* `Array.prototype.filter` and `map` is not sufficient on its own: both build their result through
|
|
437
|
+
* ArraySpeciesCreate, which reads `constructor` off the receiver and `Symbol.species` off that, and
|
|
438
|
+
* the species descriptor is configurable. A species returning `{ length: 0 }` takes every match as
|
|
439
|
+
* an indexed property while the length stays zero, so the result reads as EMPTY, and empty is rarely
|
|
440
|
+
* inert: an empty subject-alternative-name selection sends a hostname check to its common-name
|
|
441
|
+
* fallback, an empty permitted-subtree list reads as "this issuer constrains no name of that form"
|
|
442
|
+
* and skips the check, and an empty quality-of-protection list reads as a challenge offering none.
|
|
443
|
+
* A species returning a longer object substitutes the elements instead, which is how a fabricated
|
|
444
|
+
* certificate chain or anchor set reaches a verify. These append into an array literal, which is
|
|
445
|
+
* created through no protocol. Use them wherever the result feeds a refusal.
|
|
446
|
+
*
|
|
447
|
+
* There is no rename-proof code shape to detect, because `intrinsic.map` stays the right spelling
|
|
448
|
+
* wherever the result only feeds a report and is wrong only where it feeds a refusal, so a lexical
|
|
449
|
+
* detector on the call would fire across most of the tree. The guard is the conformance vector in
|
|
450
|
+
* `guard-intrinsic.test.js`, which installs a hostile `Array[Symbol.species]` and asserts in the
|
|
451
|
+
* same run that the captured operation IS steered and these are not. */
|
|
452
|
+
/** @internal The element at one index, read as an OWN property. A list with a HOLE answers from its
|
|
453
|
+
* prototype at that index, so a numeric cell installed on `Array.prototype` is read as if the list
|
|
454
|
+
* held it: measured, a caller's one-element sparse allow-list carrying no origin of its own admitted
|
|
455
|
+
* a response whose origin sat on the prototype, and the check reported the origin as verified. A
|
|
456
|
+
* hole is the absence of an element, so it reads as `undefined` here. Every verb below reads its
|
|
457
|
+
* elements this way. */
|
|
458
|
+
function _ownAt(list, i) {
|
|
459
|
+
/** @internal Existence and value come from ONE operation. Asking `hasOwn` and then indexing is two,
|
|
460
|
+
* and a proxy whose `getOwnPropertyDescriptor` trap reports the element and then deletes it
|
|
461
|
+
* answers the first with yes and the second from the prototype, which is the inherited read this
|
|
462
|
+
* exists to prevent. A descriptor carries the value for a data property; an accessor's getter is
|
|
463
|
+
* the caller's own and is called once. */
|
|
464
|
+
var d = _getOwnPropertyDescriptor(list, i);
|
|
465
|
+
if (d === undefined) return undefined;
|
|
466
|
+
if (_hasOwn(d, "value")) return d.value;
|
|
467
|
+
return typeof d.get === "function" ? _reflectApply(d.get, list, []) : undefined;
|
|
468
|
+
}
|
|
469
|
+
// @enforced-by behavioral -- a RED vector installs a hostile Array species and pins both outcomes
|
|
470
|
+
function mapList(list, fn) {
|
|
471
|
+
var out = [];
|
|
472
|
+
var n = _ownLength(list, "mapList");
|
|
473
|
+
for (var i = 0; i < n; i++) _appendOwn(out, i, fn(_ownAt(list, i), i, list));
|
|
474
|
+
return out;
|
|
475
|
+
}
|
|
476
|
+
// @enforced-by behavioral -- the same RED vector pins the selection form
|
|
477
|
+
function selectList(list, pred) {
|
|
478
|
+
var out = [];
|
|
479
|
+
var n = _ownLength(list, "selectList"), k = 0;
|
|
480
|
+
/** @internal Each element is read ONCE: the value the predicate decides on is the value that goes
|
|
481
|
+
* into the result. Written as `pred(list[i]) && append(list[i])` it reads the slot twice, so an
|
|
482
|
+
* element with a getter answers the test with one value and supplies another, which is the shape
|
|
483
|
+
* where a selection that gates a refusal admits what the refusal examined. */
|
|
484
|
+
for (var i = 0; i < n; i++) {
|
|
485
|
+
var v = _ownAt(list, i);
|
|
486
|
+
if (pred(v, i, list)) _appendOwn(out, k++, v);
|
|
487
|
+
}
|
|
488
|
+
return out;
|
|
489
|
+
}
|
|
490
|
+
/** @internal A copy that consults no construction protocol. `Array.prototype.slice` runs
|
|
491
|
+
* ArraySpeciesCreate like the selections above, so a species answering with an object of its own
|
|
492
|
+
* receives the elements and the length write: a copy of a certificate chain that discards them left
|
|
493
|
+
* an empty path, and an empty path reads as "nothing left to validate" where a self-presented anchor
|
|
494
|
+
* had just been stripped, so the chain reported trusted with no path validated at all. */
|
|
495
|
+
/** @internal A join that consults no construction protocol. `concat` reads
|
|
496
|
+
* `Symbol.isConcatSpreadable` off each operand and builds its result through ArraySpeciesCreate, so
|
|
497
|
+
* a `false` there leaves an operand NESTED inside the result where a per-element field test finds
|
|
498
|
+
* nothing to recognize, and a hostile species discards the elements outright. A join that drops an
|
|
499
|
+
* excluded-subtree list loses the exclusion, and one that drops a chain element shortens the path
|
|
500
|
+
* that gets validated. */
|
|
501
|
+
// @enforced-by behavioral -- the same RED vector pins the join form
|
|
502
|
+
function concatList(a, b) {
|
|
503
|
+
var out = copyList(a);
|
|
504
|
+
/** @internal The offset the second operand lands at comes from the COPY, not from re-reading the
|
|
505
|
+
* first operand's length. Re-read, an element getter that ran during the copy could have changed
|
|
506
|
+
* that length in between, so the second operand would overwrite copied entries or leave holes. */
|
|
507
|
+
var k = _ownLength(out, "concatList");
|
|
508
|
+
var n = _ownLength(b, "concatList");
|
|
509
|
+
for (var i = 0; i < n; i++) _appendOwn(out, k + i, _ownAt(b, i));
|
|
510
|
+
return out;
|
|
511
|
+
}
|
|
512
|
+
// @enforced-by behavioral -- the same RED vector pins the copy form
|
|
513
|
+
function copyList(list, start, end) {
|
|
514
|
+
var n = _ownLength(list, "copyList");
|
|
515
|
+
var s0 = _ownBound(start, 0, "copyList");
|
|
516
|
+
var e0 = _ownBound(end, n, "copyList");
|
|
517
|
+
var s = s0 < 0 ? (n + s0 < 0 ? 0 : n + s0) : (s0 > n ? n : s0);
|
|
518
|
+
var e = e0 < 0 ? (n + e0 < 0 ? 0 : n + e0) : (e0 > n ? n : e0);
|
|
519
|
+
var out = [];
|
|
520
|
+
var k = 0;
|
|
521
|
+
for (var i = s; i < e; i++) _appendOwn(out, k++, _ownAt(list, i));
|
|
522
|
+
return out;
|
|
523
|
+
}
|
|
105
524
|
/** @internal The in-place sort, captured at load. A DER SET OF is ordered by its encoded bytes, so the
|
|
106
525
|
* sort decides the bytes emitted: MEASURED, a replaced `slice` or `sort` made an attribute set encode a
|
|
107
526
|
* member other than the one that was validated, on a path whose output is then signed. */
|
|
@@ -136,7 +555,40 @@ var _mapHas = uncurry(Map.prototype.has);
|
|
|
136
555
|
var _weakGet = uncurry(WeakMap.prototype.get);
|
|
137
556
|
var _weakSet = uncurry(WeakMap.prototype.set);
|
|
138
557
|
var _weakHas = uncurry(WeakMap.prototype.has);
|
|
558
|
+
/** @internal A WeakSet's own pair. `WeakMap.prototype.has` throws on a WeakSet receiver, so a module
|
|
559
|
+
* marking objects in a WeakSet needs these rather than the WeakMap captures above. A marker read
|
|
560
|
+
* this way is what says an object came from a verifying producer rather than from a caller. */
|
|
561
|
+
var _weakSetAdd = uncurry(WeakSet.prototype.add);
|
|
562
|
+
var _weakSetHas = uncurry(WeakSet.prototype.has);
|
|
139
563
|
var _taSet = uncurry(Uint8Array.prototype.set);
|
|
564
|
+
/** @internal The three accessors a byte view is described by, taken off `%TypedArray%.prototype`
|
|
565
|
+
* itself so none of them is read through a replaceable property at the call. */
|
|
566
|
+
var _taProto = _getPrototypeOf(Uint8Array.prototype);
|
|
567
|
+
var _taBuffer = getter(_taProto, "buffer", "%TypedArray%.prototype");
|
|
568
|
+
var _taByteOffset = getter(_taProto, "byteOffset", "%TypedArray%.prototype");
|
|
569
|
+
var _taLength = getter(_taProto, "length", "%TypedArray%.prototype");
|
|
570
|
+
/** @internal A byte slice that consults NO construction protocol. `subarray` runs
|
|
571
|
+
* TypedArraySpeciesCreate, which reads `constructor` off the receiver and then `Symbol.species` off
|
|
572
|
+
* that, so a hostile species returns a fabricated object in place of the slice: answering with the
|
|
573
|
+
* expected RP ID hash for a 32-byte slice made an assertion produced for another relying party
|
|
574
|
+
* satisfy `expectedRpId`, while the signature was still verified over the original bytes. This
|
|
575
|
+
* builds the view from the buffer and offset directly, which is what `subarray` would have produced
|
|
576
|
+
* and shares the same memory, so it is a drop-in for it.
|
|
577
|
+
*
|
|
578
|
+
* `intrinsic.subarray` stays correct wherever the slice only feeds a length or a copy, so no
|
|
579
|
+
* rename-proof shape separates the two uses. The guard is the conformance vector in
|
|
580
|
+
* `guard-intrinsic.test.js`, which poisons a buffer's own `constructor` with a hostile species and
|
|
581
|
+
* asserts in the same run that `subarray` IS steered and this one is not. */
|
|
582
|
+
// @enforced-by behavioral -- a RED vector poisons a buffer's constructor and pins both outcomes
|
|
583
|
+
function byteSlice(buf, start, end) {
|
|
584
|
+
var len = _taLength(buf);
|
|
585
|
+
var s0 = _ownBound(start, 0, "byteSlice");
|
|
586
|
+
var e0 = _ownBound(end, len, "byteSlice");
|
|
587
|
+
var s = s0 < 0 ? 0 : (s0 > len ? len : s0);
|
|
588
|
+
var e = e0 > len ? len : e0;
|
|
589
|
+
if (e < s) e = s;
|
|
590
|
+
return _bufferFrom(_taBuffer(buf), _taByteOffset(buf) + s, e - s);
|
|
591
|
+
}
|
|
140
592
|
var _hasOwn = uncurry(Object.prototype.hasOwnProperty);
|
|
141
593
|
var _String = String;
|
|
142
594
|
var _Number = Number;
|
|
@@ -224,6 +676,12 @@ module.exports = Object.freeze({
|
|
|
224
676
|
byteLength: _bufferByteLength,
|
|
225
677
|
compare: _bufferCompare,
|
|
226
678
|
bufferEquals: _bufferEquals,
|
|
679
|
+
readUInt8: _readUInt8,
|
|
680
|
+
readUInt16BE: _readUInt16BE,
|
|
681
|
+
readUInt32BE: _readUInt32BE,
|
|
682
|
+
readUIntBE: _readUIntBE,
|
|
683
|
+
writeUInt16BE: _writeUInt16BE,
|
|
684
|
+
writeUInt32BE: _writeUInt32BE,
|
|
227
685
|
keyEquals: _keyEquals,
|
|
228
686
|
isView: _isView,
|
|
229
687
|
isInteger: _isInteger,
|
|
@@ -240,6 +698,7 @@ module.exports = Object.freeze({
|
|
|
240
698
|
assign: _objectAssign,
|
|
241
699
|
freeze: _objectFreeze,
|
|
242
700
|
isExtensible: _isExtensible,
|
|
701
|
+
isFrozen: _isFrozen,
|
|
243
702
|
ownKeys: _ownKeys,
|
|
244
703
|
stringify: _jsonStringify,
|
|
245
704
|
floor: _mathFloor,
|
|
@@ -269,6 +728,7 @@ module.exports = Object.freeze({
|
|
|
269
728
|
promiseAny: _promiseAny,
|
|
270
729
|
promiseTry: _promiseTry,
|
|
271
730
|
promiseWithResolvers: _promiseWithResolvers,
|
|
731
|
+
chain: chain,
|
|
272
732
|
setter: setter,
|
|
273
733
|
URL: _URL,
|
|
274
734
|
urlCanParse: _urlCanParse,
|
|
@@ -293,6 +753,17 @@ module.exports = Object.freeze({
|
|
|
293
753
|
every: _arrEvery,
|
|
294
754
|
some: _arrSome,
|
|
295
755
|
indexOf: _arrIndexOf,
|
|
756
|
+
reduce: _arrReduce,
|
|
757
|
+
mapList: mapList,
|
|
758
|
+
selectList: selectList,
|
|
759
|
+
ownIndexOf: ownIndexOf,
|
|
760
|
+
everyOwn: everyOwn,
|
|
761
|
+
allOf: allOf,
|
|
762
|
+
settledOf: settledOf,
|
|
763
|
+
copyList: copyList,
|
|
764
|
+
concatList: concatList,
|
|
765
|
+
splitChar: splitChar,
|
|
766
|
+
append: append,
|
|
296
767
|
sort: _arrSort,
|
|
297
768
|
concat: _arrConcat,
|
|
298
769
|
arraySlice: _arrSlice,
|
|
@@ -324,7 +795,10 @@ module.exports = Object.freeze({
|
|
|
324
795
|
weakGet: _weakGet,
|
|
325
796
|
weakSet: _weakSet,
|
|
326
797
|
weakHas: _weakHas,
|
|
798
|
+
weakSetAdd: _weakSetAdd,
|
|
799
|
+
weakSetHas: _weakSetHas,
|
|
327
800
|
typedArraySet: _taSet,
|
|
801
|
+
byteSlice: byteSlice,
|
|
328
802
|
Set: _Set,
|
|
329
803
|
Map: _Map,
|
|
330
804
|
WeakMap: _WeakMap,
|