@blamejs/pki 0.9.5 → 0.9.7

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 (47) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +7 -6
  3. package/bin/pki.js +110 -34
  4. package/lib/acme.js +91 -46
  5. package/lib/asn1-der.js +6 -5
  6. package/lib/attrcert-sign.js +4 -3
  7. package/lib/cmp-build.js +16 -6
  8. package/lib/cmp-session.js +26 -3
  9. package/lib/cmp-verify.js +24 -2
  10. package/lib/cms-compress.js +3 -3
  11. package/lib/cms-digest.js +3 -3
  12. package/lib/cms-verify.js +18 -8
  13. package/lib/compromised-keys.js +114 -0
  14. package/lib/constants.js +1 -0
  15. package/lib/crl-sign.js +3 -3
  16. package/lib/crmf-sign.js +2 -0
  17. package/lib/csr-sign.js +5 -1
  18. package/lib/ct.js +16 -3
  19. package/lib/est.js +44 -29
  20. package/lib/framework-error.js +20 -7
  21. package/lib/guard-all.js +2 -0
  22. package/lib/guard-distrust.js +344 -0
  23. package/lib/guard-json.js +1 -1
  24. package/lib/guard-verdict.js +16 -3
  25. package/lib/http-transport.js +412 -41
  26. package/lib/jose.js +1 -1
  27. package/lib/lint.js +49 -7
  28. package/lib/ocsp-verify.js +9 -3
  29. package/lib/ocsp.js +8 -4
  30. package/lib/oid.js +4 -0
  31. package/lib/path-validate.js +131 -16
  32. package/lib/possession.js +6 -2
  33. package/lib/related-cert.js +2 -2
  34. package/lib/revocation-fetch.js +39 -9
  35. package/lib/scep.js +28 -13
  36. package/lib/schema-pkix.js +3 -3
  37. package/lib/sigstore.js +11 -6
  38. package/lib/smime.js +18 -13
  39. package/lib/tls-cert-compress.js +6 -5
  40. package/lib/trust.js +159 -20
  41. package/lib/trustanchor-build.js +16 -1
  42. package/lib/tsp-sign.js +7 -1
  43. package/lib/webauthn-mds.js +30 -8
  44. package/lib/webauthn.js +46 -14
  45. package/lib/x509-sign.js +16 -5
  46. package/package.json +1 -1
  47. package/sbom.cdx.json +6 -6
@@ -78,10 +78,23 @@ function _isCodeShape(c) {
78
78
  * if (e instanceof pki.errors.PkiError) console.error(e.code);
79
79
  * }
80
80
  */
81
+ /** @internal A field of an error, defined as an own data property the way an assignment to a plain
82
+ * object creates one. An assignment runs a setter inherited from `Object.prototype`, and a setter
83
+ * that throws turned the construction of every error into that throw. The descriptor has no
84
+ * prototype, since `defineProperty` reads an inherited `get` or `set` off a literal one. */
85
+ function _own(target, key, value) {
86
+ var d = intrinsic.create(null);
87
+ d.value = value;
88
+ d.writable = true;
89
+ d.enumerable = true;
90
+ d.configurable = true;
91
+ _defineProperty(target, key, d);
92
+ }
93
+
81
94
  class PkiError extends Error {
82
95
  constructor(message, code) {
83
96
  super(message);
84
- this.name = "PkiError";
97
+ _own(this, "name", "PkiError");
85
98
  var c = code || "pki/invalid";
86
99
  if (typeof c !== "string" || !_isCodeShape(c)) {
87
100
  throw new TypeError(
@@ -89,9 +102,9 @@ class PkiError extends Error {
89
102
  " (PkiError takes (message, code); defineClass subclasses take (code, message))"
90
103
  );
91
104
  }
92
- this.code = c;
93
- this.isPkiError = true;
94
- this.permanent = !_TRANSIENT_REASONS[_reasonOf(c)];
105
+ _own(this, "code", c);
106
+ _own(this, "isPkiError", true);
107
+ _own(this, "permanent", !_TRANSIENT_REASONS[_reasonOf(c)]);
95
108
  }
96
109
  }
97
110
 
@@ -129,10 +142,10 @@ function defineClass(name, opts) {
129
142
  var GeneratedError = class extends PkiError {
130
143
  constructor(code, message, arg3) {
131
144
  super(message, code);
132
- this.name = name;
133
- this[flagKey] = true;
145
+ _own(this, "name", name);
146
+ _own(this, flagKey, true);
134
147
  if (withCause) {
135
- if (arg3 !== undefined) this.cause = arg3;
148
+ if (arg3 !== undefined) _own(this, "cause", arg3);
136
149
  } else if (arg3 !== undefined) {
137
150
  throw new TypeError(name + " takes (code, message); to thread a cause, define the class with { withCause: true }");
138
151
  }
package/lib/guard-all.js CHANGED
@@ -22,6 +22,7 @@ var secret = require("./guard-secret");
22
22
  var parsed = require("./guard-parsed");
23
23
  var verdict = require("./guard-verdict");
24
24
  var async_ = require("./guard-async");
25
+ var distrust = require("./guard-distrust");
25
26
 
26
27
  module.exports = _freeze({
27
28
  bytes: bytes,
@@ -42,4 +43,5 @@ module.exports = _freeze({
42
43
  parsed: parsed,
43
44
  verdict: verdict,
44
45
  async: async_,
46
+ distrust: distrust,
45
47
  });
@@ -0,0 +1,344 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) blamejs contributors
3
+ "use strict";
4
+ // @internal
5
+
6
+ var util = require("util");
7
+ var intrinsic = require("./guard-intrinsic");
8
+ var constants = require("./constants");
9
+ var gBytes = require("./guard-bytes");
10
+ var gList = require("./guard-list");
11
+ var gCrypto = require("./guard-crypto");
12
+ var compromisedKeys = require("./compromised-keys");
13
+
14
+ var _freeze = intrinsic.freeze;
15
+ var _isArray = intrinsic.isArray;
16
+ var _create = intrinsic.create;
17
+ var _hasOwn = intrinsic.hasOwn;
18
+ var _getOwnPropertyDescriptor = intrinsic.getOwnPropertyDescriptor;
19
+ var _bufToString = intrinsic.bufToString;
20
+ var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
21
+ var _fromCharCode = intrinsic.fromCharCode;
22
+ var _isProxy = util.types.isProxy;
23
+
24
+ var DIGEST_BYTES = 32;
25
+ var DIGEST_HEX = 64;
26
+
27
+ /** @internal One hexadecimal character, folded to lower case, or -1. The fold is arithmetic on the
28
+ * character code, so the normalized digest is not the answer of a `toLowerCase` read off the live
29
+ * prototype. */
30
+ function _lowerHexCode(c) {
31
+ if (c >= 48 && c <= 57) return c;
32
+ if (c >= 97 && c <= 102) return c;
33
+ if (c >= 65 && c <= 70) return c + 32;
34
+ return -1;
35
+ }
36
+
37
+ function _hexEntry(s, E, code, where) {
38
+ if (s.length !== DIGEST_HEX) {
39
+ throw E(code, where + " must be a SHA-256 digest of a SubjectPublicKeyInfo: 64 hexadecimal characters or 32 bytes, got " + s.length + " characters");
40
+ }
41
+ var out = "";
42
+ for (var i = 0; i < DIGEST_HEX; i++) {
43
+ var c = _lowerHexCode(_charCodeAt(s, i));
44
+ if (c === -1) throw E(code, where + " must be 64 hexadecimal characters with no separators; character " + i + " is not a hexadecimal digit");
45
+ out += _fromCharCode(c);
46
+ }
47
+ return out;
48
+ }
49
+
50
+ function _bytesEntry(v, E, code, where) {
51
+ var copy = gBytes.snapshotSource(v, E, code, where);
52
+ if (copy.length !== DIGEST_BYTES) {
53
+ throw E(code, where + " must be a SHA-256 digest of a SubjectPublicKeyInfo: 32 bytes or 64 hexadecimal characters, got " + copy.length + " bytes");
54
+ }
55
+ return _bufToString(copy, "hex");
56
+ }
57
+
58
+ /** The caller's list of distrusted keys, read once and returned as a frozen list of lower-case hex
59
+ * digests with duplicates removed, or `null` when the option is absent or `null`. Each entry is the
60
+ * SHA-256 digest of a certificate's DER SubjectPublicKeyInfo, given as 64 hexadecimal characters or
61
+ * as 32 bytes.
62
+ *
63
+ * Every slot is read through its descriptor, so a hole, an accessor and a Proxy are refused rather
64
+ * than read: a hole is answered by the array prototype and an accessor answers each read separately,
65
+ * and either one makes the list the check uses differ from the list the caller wrote. The list is a
66
+ * refusal list, so reading it as shorter than it is lets through a key the caller distrusted.
67
+ *
68
+ * @enforced-by behavioral -- the defect is a door that does not call this, which has no rename-proof
69
+ * code shape; the guard is the RED vector each verb carries, driving a listed key through the
70
+ * shipped verb and asserting the refusal.
71
+ */
72
+ function keys(value, E, code, label) {
73
+ if (value === undefined || value === null) return null;
74
+ if (typeof value !== "object" || _isProxy(value) || !_isArray(value)) {
75
+ throw E(code, label + " must be an array of SHA-256 SubjectPublicKeyInfo digests");
76
+ }
77
+ var n = gList.count(value, "keys");
78
+ if (n > constants.LIMITS.DISTRUSTED_KEYS_MAX) {
79
+ throw E(code, label + " has " + n + " entries, more than the " + constants.LIMITS.DISTRUSTED_KEYS_MAX + " this toolkit reads");
80
+ }
81
+ var seen = _create(null);
82
+ var out = [];
83
+ for (var i = 0; i < n; i++) {
84
+ var where = label + "[" + i + "]";
85
+ var d = _getOwnPropertyDescriptor(value, i);
86
+ if (!d) throw E(code, where + " is a hole; every entry must be present");
87
+ if (d.get || d.set) throw E(code, where + " is an accessor; every entry must be a data property");
88
+ var v = d.value;
89
+ var hex;
90
+ if (typeof v === "string") hex = _hexEntry(v, E, code, where);
91
+ else if (gBytes.isByteSource(v)) hex = _bytesEntry(v, E, code, where);
92
+ else throw E(code, where + " must be 64 hexadecimal characters or 32 bytes");
93
+ if (_hasOwn(seen, hex)) continue;
94
+ seen[hex] = true;
95
+ gList.append(out, hex);
96
+ }
97
+ return _freeze(out);
98
+ }
99
+
100
+ /** The lower-case hex SHA-256 of `spkiBytes`, the DER SubjectPublicKeyInfo exactly as a certificate
101
+ * or an anchor carries it.
102
+ *
103
+ * @enforced-by behavioral -- a digest has no rename-proof shape that separates this use from the
104
+ * others `guard-crypto` serves; the guard is the membership vector, which fails if the bytes hashed
105
+ * are not the ones listed.
106
+ */
107
+ function digest(spkiBytes) {
108
+ return gCrypto.digest("sha256", spkiBytes, { output: "hex" });
109
+ }
110
+
111
+ /** @internal The codec and the registry, reached through inline requires: both load this module
112
+ * through guard-all, so both are loaded by the time a digest is asked for. */
113
+ function _codec() {
114
+ return {
115
+ asn1: require("./asn1-der"), // allow:inline-require -- circular load: asn1-der -> guard-all -> this module
116
+ oid: require("./oid"), // allow:inline-require -- circular load: oid -> guard-all -> this module
117
+ };
118
+ }
119
+
120
+ /** @internal The SubjectPublicKeyInfo with an identifier that restricts the key's use replaced by the
121
+ * key's own: id-ecDH and id-ecMQV (RFC 5480 sec. 2.1.2) become ecPublicKey with the curve kept, and
122
+ * RSASSA-PSS and RSAES-OAEP (RFC 4055) become rsaEncryption with NULL. The subjectPublicKey bits are
123
+ * the same key in each pair. Any other identifier is returned unchanged. */
124
+ function _unrestricted(spkiBytes, c) {
125
+ var b = c.asn1.build;
126
+ var root = c.asn1.decode(spkiBytes);
127
+ var alg = root.children[0];
128
+ var name = c.oid.name(c.asn1.read.oid(alg.children[0]));
129
+ if (name === "ecDH" || name === "ecMQV") {
130
+ var params = alg.children.length > 1 ? [b.raw(alg.children[1].bytes)] : [];
131
+ return b.sequence([b.sequence(intrinsic.concatList([b.oid(c.oid.byName("ecPublicKey"))], params)), b.raw(root.children[1].bytes)]);
132
+ }
133
+ if (name === "rsassaPss" || name === "rsaesOaep") {
134
+ return b.sequence([b.sequence([b.oid(c.oid.byName("rsaEncryption")), b.nullValue()]), b.raw(root.children[1].bytes)]);
135
+ }
136
+ return spkiBytes;
137
+ }
138
+
139
+ /** @internal The key in canonical form, or null when node does not read the bytes as a public key.
140
+ * An elliptic curve key is written with ecPublicKey, its named curve and an uncompressed point,
141
+ * whatever point form or parameter form it was read in. Any other key node writes as a JWK is
142
+ * written the way node writes a key it builds from one, which puts an RSA key under rsaEncryption
143
+ * with NULL. A key with neither form is re-exported as node read it. */
144
+ function _canonicalSpki(spkiBytes) {
145
+ try {
146
+ var c = _codec();
147
+ var spki = _unrestricted(spkiBytes, c);
148
+ var key = gCrypto.publicKey({ key: spki, format: "der", type: "spki" });
149
+ if (gCrypto.keyTypeOf(key) === "ec") {
150
+ var details = gCrypto.keyDetailsOf(key);
151
+ var curveOid = details && typeof details.namedCurve === "string" ? c.oid.byName(details.namedCurve) : undefined;
152
+ if (curveOid !== undefined) {
153
+ var b = c.asn1.build;
154
+ var point = c.asn1.read.bitString(c.asn1.decode(spki).children[1]).bytes;
155
+ var uncompressed = gCrypto.ecConvertPoint(point, details.namedCurve, "uncompressed");
156
+ return b.sequence([b.sequence([b.oid(c.oid.byName("ecPublicKey")), b.oid(curveOid)]), b.bitString(uncompressed, 0)]);
157
+ }
158
+ }
159
+ var jwk = null;
160
+ try { jwk = gCrypto.exportKey(key, { format: "jwk" }); }
161
+ catch (_je) {
162
+ // allow:swallow-unverified a key type with no JWK form is re-exported as node read it
163
+ jwk = null;
164
+ }
165
+ if (jwk !== null) key = gCrypto.publicKey({ key: jwk, format: "jwk" });
166
+ return gCrypto.exportKey(key, { type: "spki", format: "der" });
167
+ } catch (_e) {
168
+ // allow:swallow-unverified a key node does not read has no second encoding, and the raw digest still decides
169
+ return null;
170
+ }
171
+ }
172
+
173
+ /** The digest a distrust entry names a key by: the lower-case hex SHA-256 of the key's
174
+ * SubjectPublicKeyInfo in canonical form, an uncompressed EC point with its named curve and an RSA
175
+ * key with NULL parameters. That is how nearly every certificate encodes a key, so for those it is
176
+ * the digest of the bytes the certificate carries. A key node does not read is digested as given.
177
+ *
178
+ * @enforced-by behavioral -- a digest has no rename-proof shape; the guard is the two-direction
179
+ * re-encoding vectors in guard-distrust.test.js.
180
+ */
181
+ function keyDigest(spkiBytes) {
182
+ var canonical = _canonicalSpki(spkiBytes);
183
+ return digest(canonical !== null ? canonical : spkiBytes);
184
+ }
185
+
186
+ /** @internal The built-in list, keyed by digest. */
187
+ var COMPROMISED = _create(null);
188
+ for (var _ci = 0; _ci < compromisedKeys.KEYS.length; _ci++) COMPROMISED[compromisedKeys.KEYS[_ci].spkiSha256] = compromisedKeys.KEYS[_ci];
189
+
190
+ /** @internal The curves the small-scalar table is built for, by JWK curve name, with the width of a
191
+ * coordinate in bytes, and the scalar bound. Each table holds the x-coordinates of d*G for d from 1
192
+ * to the bound minus one, built once per curve on first use (measured on Node 26: 4 ms for P-256,
193
+ * 138 ms for P-384, 321 ms for P-521). The points d*G and (n-d)*G share an x-coordinate, so one
194
+ * comparison covers both. */
195
+ var SMALL_SCALAR_CURVES = intrinsic.assign(_create(null), {
196
+ "P-256": { name: "prime256v1", width: 32 },
197
+ "P-384": { name: "secp384r1", width: 48 },
198
+ "P-521": { name: "secp521r1", width: 66 },
199
+ "secp256k1": { name: "secp256k1", width: 32 },
200
+ });
201
+ var SMALL_SCALAR_BOUND = 256;
202
+ var _smallScalarTables = _create(null);
203
+ function _smallScalarTable(curve) {
204
+ if (_smallScalarTables[curve.name]) return _smallScalarTables[curve.name];
205
+ var table = _create(null);
206
+ var scalar = intrinsic.bufferAlloc(curve.width);
207
+ for (var d = 1; d < SMALL_SCALAR_BOUND; d++) {
208
+ scalar[curve.width - 1] = d;
209
+ table[_bufToString(gCrypto.ecPointFromScalar(curve.name, scalar), "hex", 1, 1 + curve.width)] = true;
210
+ }
211
+ _smallScalarTables[curve.name] = table;
212
+ return table;
213
+ }
214
+
215
+ /** The curve name of an elliptic curve key whose private scalar is below 256, or below 256 short of
216
+ * the group order, or `null` for any other key. Anyone can recover such a private key from the public
217
+ * key by trying each candidate. The key is read through node's own import after an id-ecDH or
218
+ * id-ecMQV identifier is read as ecPublicKey, so a named or explicit curve and an uncompressed,
219
+ * compressed or hybrid point are all judged; a point that is not on the curve is not a key and
220
+ * answers `null`. The covered curves are P-256, P-384, P-521 and secp256k1.
221
+ *
222
+ * @enforced-by behavioral -- the defect is a curve or an encoding the table does not reach, which has
223
+ * no code shape; the guard is the per-curve and per-encoding vectors in guard-distrust.test.js and
224
+ * lint-key-compromise.test.js.
225
+ */
226
+ function smallEcScalar(spkiBytes) {
227
+ var jwk;
228
+ try {
229
+ var spki = _unrestricted(spkiBytes, _codec());
230
+ var key = gCrypto.publicKey({ key: spki, format: "der", type: "spki" });
231
+ if (gCrypto.keyTypeOf(key) !== "ec") return null;
232
+ jwk = gCrypto.exportKey(key, { format: "jwk" });
233
+ } catch (_e) {
234
+ // allow:swallow-unverified a key node does not import as an elliptic curve point has no scalar to judge
235
+ return null;
236
+ }
237
+ var curve = typeof jwk.crv === "string" && _hasOwn(SMALL_SCALAR_CURVES, jwk.crv) ? SMALL_SCALAR_CURVES[jwk.crv] : null;
238
+ if (curve === null || typeof jwk.x !== "string") return null;
239
+ return _smallScalarTable(curve)[_bufToString(intrinsic.bufferFrom(jwk.x, "base64url"), "hex")] === true ? curve.name : null;
240
+ }
241
+
242
+ /** Why the private key of `spkiBytes` is public, as one sentence, or `null`. A key is compromised
243
+ * when its digest, as given or as `keyDigest` computes it, is on the list `pki.trust.knownCompromisedKeys()`
244
+ * returns, or when `smallEcScalar` answers a curve for it. Every verifier in this toolkit refuses such
245
+ * a key, with no option that turns the refusal off.
246
+ *
247
+ * @enforced-by behavioral -- the defect is a door that does not refuse, which has no rename-proof code
248
+ * shape; every door reaches this through `has`, and the guard is the compromised-key vector each verb
249
+ * carries.
250
+ */
251
+ function compromised(spkiBytes) {
252
+ if (spkiBytes === null || spkiBytes === undefined) return null;
253
+ var entry = COMPROMISED[digest(spkiBytes)] || COMPROMISED[keyDigest(spkiBytes)];
254
+ if (entry) return "the key is the published key of " + entry.name + ": " + entry.reason;
255
+ var curve = smallEcScalar(spkiBytes);
256
+ if (curve !== null) return "the " + curve + " private key is an integer below " + SMALL_SCALAR_BOUND + ", so anyone can recover it from the public key";
257
+ return null;
258
+ }
259
+
260
+ /** Throws `E(code, ...)` when `compromised(spkiBytes)` answers, naming the key by `label` and saying
261
+ * why its private key is public. A verb that certifies a key, signs with one or requests a
262
+ * certificate for one calls this on each key it is handed.
263
+ *
264
+ * @enforced-by behavioral -- the defect is a signing verb that does not call this, which has no
265
+ * rename-proof code shape; the guard is the compromised-key vector each signing verb carries.
266
+ */
267
+ function refuseCompromised(spkiBytes, E, code, label) {
268
+ var why = compromised(spkiBytes);
269
+ if (why !== null) throw E(code, label + " is a compromised key: " + why);
270
+ }
271
+
272
+ /** Why the key `spkiBytes` names is refused, as the end of a sentence about the key, or `null` when
273
+ * `has(list, spkiBytes)` is false: "is a compromised key: " and the `compromised` reason, or "is
274
+ * listed in " and `label`, the option the caller's list came from.
275
+ *
276
+ * @enforced-by behavioral -- a message has no rename-proof code shape; the guard is the vectors that
277
+ * assert each door's message names a compromised key as one and a listed key as listed.
278
+ */
279
+ function refusal(list, spkiBytes, label) {
280
+ var why = compromised(spkiBytes);
281
+ if (why !== null) return "is a compromised key: " + why;
282
+ return has(list, spkiBytes) ? "is listed in " + label : null;
283
+ }
284
+
285
+ /** Whether the key `spkiBytes` names is refused: it is compromised (see `compromised`), or it is on
286
+ * `list`, a value `keys` returned. A `null` or empty list still refuses a compromised key. The digest
287
+ * of the bytes as given is compared with the list, and so is `keyDigest`, so an entry `keyDigest`
288
+ * computed matches the key however a certificate encodes it (a compressed EC point, RSA parameters
289
+ * without NULL), and an entry computed over raw bytes matches a certificate with the same bytes.
290
+ *
291
+ * @enforced-by behavioral -- membership has no rename-proof code shape; the RED vectors are the
292
+ * listed-key and compromised-key refusals at each verb, and the re-encodings in guard-distrust.test.js
293
+ * in both directions.
294
+ */
295
+ function has(list, spkiBytes) {
296
+ if (spkiBytes === null || spkiBytes === undefined) return false;
297
+ if (compromised(spkiBytes) !== null) return true;
298
+ if (list === null || list === undefined || list.length === 0) return false;
299
+ if (gList.contains(list, digest(spkiBytes))) return true;
300
+ return gList.contains(list, keyDigest(spkiBytes));
301
+ }
302
+
303
+ /** Every entry of two lists that `keys` returned, once, as a frozen list; `null` when both are
304
+ * `null`. A transport default and a per-request list are combined this way, so a request cannot
305
+ * remove a key the default distrusts by naming a shorter list.
306
+ *
307
+ * @enforced-by behavioral -- a union has no rename-proof code shape; the RED vector is a request
308
+ * list that omits a default entry and the default entry still being refused.
309
+ */
310
+ function union(a, b) {
311
+ if ((a === null || a === undefined) && (b === null || b === undefined)) return null;
312
+ var seen = _create(null);
313
+ var out = [];
314
+ var parts = [a || [], b || []];
315
+ for (var p = 0; p < 2; p++) {
316
+ var part = parts[p];
317
+ for (var i = 0, n = gList.count(part, "union"); i < n; i++) {
318
+ var hex = part[i];
319
+ if (_hasOwn(seen, hex)) continue;
320
+ seen[hex] = true;
321
+ gList.append(out, hex);
322
+ }
323
+ }
324
+ return _freeze(out);
325
+ }
326
+
327
+ /** A copy of the built-in list: one `{ spkiSha256, name, reason, sources }` record per key, each
328
+ * frozen, in a new array the caller may change.
329
+ *
330
+ * @enforced-by behavioral -- a copy has no rename-proof code shape; the guard is the vector that
331
+ * changes the returned array and reads the list again.
332
+ */
333
+ function knownCompromised() {
334
+ var out = [];
335
+ for (var i = 0; i < compromisedKeys.KEYS.length; i++) gList.append(out, compromisedKeys.KEYS[i]);
336
+ return out;
337
+ }
338
+
339
+ module.exports = _freeze({
340
+ keys: keys, digest: digest, keyDigest: keyDigest, has: has, union: union,
341
+ compromised: compromised, refuseCompromised: refuseCompromised, refusal: refusal,
342
+ smallEcScalar: smallEcScalar, knownCompromised: knownCompromised,
343
+ SMALL_SCALAR_BOUND: SMALL_SCALAR_BOUND,
344
+ });
package/lib/guard-json.js CHANGED
@@ -24,7 +24,7 @@ var _hexVal = require("./guard-encoding").hexNibble;
24
24
  // @enforced-by json-parse-not-via-guard
25
25
  function parse(input, ErrorClass, spec) {
26
26
  function E(code, message, cause) { return new ErrorClass(code, message, cause); }
27
- if (spec.maxBytes === undefined || spec.maxDepth === undefined) {
27
+ if (spec.maxBytes == null || spec.maxDepth == null) {
28
28
  throw new TypeError("guard.json.parse: spec.maxBytes and spec.maxDepth are required");
29
29
  }
30
30
  var maxBytes = limits.cap(spec.maxBytes, "guard.json.parse spec.maxBytes", undefined);
@@ -9,6 +9,19 @@ var _defineProperty = require("./guard-intrinsic").defineProperty;
9
9
  var _getOwnPropertyDescriptor = require("./guard-intrinsic").getOwnPropertyDescriptor;
10
10
  var _hasOwn = require("./guard-intrinsic").hasOwn;
11
11
  var _Object = require("./guard-intrinsic").Object;
12
+ var _create = require("./guard-intrinsic").create;
13
+
14
+ /** @internal A writable, configurable data descriptor with no prototype. A descriptor written as an
15
+ * object literal inherits from `Object.prototype`, and `defineProperty` reads `get` and `set` through
16
+ * that chain, so an inherited `get` beside the `value` made every define here throw. */
17
+ function _data(value, enumerable) {
18
+ var d = _create(null);
19
+ d.value = value;
20
+ d.enumerable = enumerable;
21
+ d.configurable = true;
22
+ d.writable = true;
23
+ return d;
24
+ }
12
25
 
13
26
  function _copyOwn(out, src) {
14
27
  var keys = _keys(src);
@@ -16,7 +29,7 @@ function _copyOwn(out, src) {
16
29
  var d = _getOwnPropertyDescriptor(src, keys[i]);
17
30
  if (!d) continue;
18
31
  var value = _hasOwn(d, "value") ? d.value : src[keys[i]];
19
- _defineProperty(out, keys[i], { value: value, enumerable: true, configurable: true, writable: true });
32
+ _defineProperty(out, keys[i], _data(value, true));
20
33
  }
21
34
  }
22
35
 
@@ -49,7 +62,7 @@ function shield(target) {
49
62
  * machinery looks, and reading it to decide would be the one read that does not count. */
50
63
  if (d && _hasOwn(d, "value") && typeof d.value !== "function") return target;
51
64
  }
52
- _defineProperty(target, "then", { value: undefined, enumerable: false, configurable: true, writable: true });
65
+ _defineProperty(target, "then", _data(undefined, false));
53
66
  return target;
54
67
  }
55
68
 
@@ -68,7 +81,7 @@ function carries(obj, key) {
68
81
 
69
82
  // @enforced-by behavioral -- for a target that cannot be rebuilt, an Error carrying a field a
70
83
  function set(target, key, value) {
71
- _defineProperty(target, key, { value: value, enumerable: true, configurable: true, writable: true });
84
+ _defineProperty(target, key, _data(value, true));
72
85
  /** @internal The target leaves here carrying the sentinel as well. A field set on an object is the
73
86
  * same kind of value a verdict is, and a target that reached a promise resolution without one would
74
87
  * hand the lookup to Object.prototype however it was assembled. */