@blamejs/pki 0.8.59 → 0.8.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/lib/acme.js +15 -7
  3. package/lib/alt-sig.js +3 -1
  4. package/lib/asn1-der.js +82 -34
  5. package/lib/attrcert-sign.js +19 -16
  6. package/lib/byte-writer.js +63 -13
  7. package/lib/cbor-det.js +9 -3
  8. package/lib/cmc-build.js +26 -18
  9. package/lib/cmp-build.js +35 -33
  10. package/lib/cmp-session.js +19 -9
  11. package/lib/cms-decrypt.js +37 -23
  12. package/lib/cms-digest.js +2 -3
  13. package/lib/cms-encrypt.js +38 -33
  14. package/lib/cms-sign.js +65 -43
  15. package/lib/cms-verify.js +8 -4
  16. package/lib/composite-kem.js +28 -29
  17. package/lib/crl-sign.js +24 -17
  18. package/lib/crmf-sign.js +11 -17
  19. package/lib/csr-sign.js +5 -2
  20. package/lib/ct.js +38 -25
  21. package/lib/est.js +12 -9
  22. package/lib/guard-bytes.js +5 -1
  23. package/lib/guard-crypto.js +506 -14
  24. package/lib/guard-der.js +6 -1
  25. package/lib/guard-intrinsic.js +12 -4
  26. package/lib/guard-list.js +64 -0
  27. package/lib/guard-name.js +1 -1
  28. package/lib/guard-secret.js +3 -2
  29. package/lib/hpke.js +34 -27
  30. package/lib/http-digest.js +5 -7
  31. package/lib/http-transport.js +12 -3
  32. package/lib/inspect.js +10 -2
  33. package/lib/jose.js +3 -1
  34. package/lib/key.js +41 -29
  35. package/lib/lint.js +236 -152
  36. package/lib/mime.js +9 -5
  37. package/lib/ocsp.js +26 -24
  38. package/lib/path-validate.js +43 -13
  39. package/lib/pbes2.js +12 -9
  40. package/lib/pkcs11-uri.js +3 -1
  41. package/lib/pkcs12-build.js +19 -17
  42. package/lib/pki-build.js +17 -13
  43. package/lib/possession.js +3 -1
  44. package/lib/rc2.js +6 -2
  45. package/lib/revocation-fetch.js +78 -19
  46. package/lib/scep.js +21 -14
  47. package/lib/schema-attrcert.js +4 -2
  48. package/lib/schema-c509.js +94 -78
  49. package/lib/schema-cmc.js +5 -2
  50. package/lib/schema-cmp.js +6 -3
  51. package/lib/schema-cms.js +7 -4
  52. package/lib/schema-crl.js +1 -1
  53. package/lib/schema-crmf.js +1 -1
  54. package/lib/schema-csr.js +3 -3
  55. package/lib/schema-engine.js +36 -18
  56. package/lib/schema-pkcs1.js +7 -3
  57. package/lib/schema-pkcs12.js +9 -6
  58. package/lib/schema-pkix.js +19 -3
  59. package/lib/schema-sec1.js +4 -1
  60. package/lib/schema-tsp.js +7 -4
  61. package/lib/shbs.js +10 -9
  62. package/lib/sign-scheme.js +2 -2
  63. package/lib/sigstore.js +9 -9
  64. package/lib/smime.js +19 -16
  65. package/lib/tlog.js +20 -13
  66. package/lib/tuf.js +7 -4
  67. package/lib/validator-cose.js +2 -2
  68. package/lib/validator-keydesc.js +4 -1
  69. package/lib/validator-tls.js +7 -2
  70. package/lib/webauthn-mds.js +3 -7
  71. package/lib/webauthn.js +4 -11
  72. package/lib/webcrypto.js +70 -49
  73. package/lib/x509-sign.js +20 -15
  74. package/package.json +1 -1
  75. package/sbom.cdx.json +6 -6
@@ -55,6 +55,42 @@ var _createPublicKey = nodeCrypto.createPublicKey;
55
55
  var _createPrivateKey = nodeCrypto.createPrivateKey;
56
56
  var _createSecretKey = nodeCrypto.createSecretKey;
57
57
 
58
+ /** @internal The key agreement and the key generation, captured at load. Read off the module handle
59
+ * at call time, each decides a value no later check recovers: a replaced agreement returns the
60
+ * traditional half of a shared secret outright, measured by driving `pki.hpke.decap` with one
61
+ * returning a fixed buffer, which derived a secret from the value the replacement chose; and a
62
+ * replaced generation decides the ephemeral key an encapsulation is made under. `node:crypto` is an
63
+ * ordinary module object that nothing freezes, so the handle is as replaceable as a prototype. */
64
+ var _diffieHellman = nodeCrypto.diffieHellman;
65
+ var _generateKeyPairSync = nodeCrypto.generateKeyPairSync;
66
+
67
+ /** @internal The ML-KEM encapsulation and decapsulation, and the AEAD transform constructions, all
68
+ * captured at load for the same reason as the agreement above: each returns or decides a value no
69
+ * later check recovers. `encapsulate` and `decapsulate` carry the post-quantum half of a hybrid
70
+ * shared secret, and the two transform constructions decide the cipher a seal and an open run
71
+ * under, so a replacement returns a ciphertext of its own choosing. */
72
+ var _encapsulate = nodeCrypto.encapsulate;
73
+ var _decapsulate = nodeCrypto.decapsulate;
74
+ var _createCipheriv = nodeCrypto.createCipheriv;
75
+ var _createDecipheriv = nodeCrypto.createDecipheriv;
76
+
77
+ /** @internal The randomness, the password-based and extract-and-expand KDFs, the RSA transforms and
78
+ * the ephemeral-agreement constructor, all captured at load for the same reason. Each decides a
79
+ * value outright rather than a claim about one: the randomness is where a content-encryption key, a
80
+ * nonce, an IV and a salt are born, so a replacement returning a value it knows hands it every
81
+ * message those protect; a replaced KDF decides the key-encryption key a password unwraps; and a
82
+ * replaced RSA transform decides the key-transport ciphertext a recipient receives, or the secret a
83
+ * recipient recovers from one. */
84
+ var _randomBytes = nodeCrypto.randomBytes;
85
+ var _randomFillSync = nodeCrypto.randomFillSync;
86
+ var _randomUUID = nodeCrypto.randomUUID;
87
+ var _pbkdf2Sync = nodeCrypto.pbkdf2Sync;
88
+ var _pbkdf2 = nodeCrypto.pbkdf2;
89
+ var _hkdfSync = nodeCrypto.hkdfSync;
90
+ var _publicEncrypt = nodeCrypto.publicEncrypt;
91
+ var _privateDecrypt = nodeCrypto.privateDecrypt;
92
+ var _createECDH = nodeCrypto.createECDH;
93
+
58
94
  /** @internal The three KeyObject `export` methods, captured at load. `node:crypto` exports no
59
95
  * constructor carrying them: `KeyObject.prototype` has no `export`, and `PublicKeyObject`,
60
96
  * `PrivateKeyObject` and `SecretKeyObject` each own one. So one sample pair and one secret key are
@@ -74,6 +110,68 @@ var _publicExport = intrinsic.uncurry(_publicProto.export);
74
110
  var _privateExport = intrinsic.uncurry(_privateProto.export);
75
111
  var _secretExport = intrinsic.uncurry(_secretProto.export);
76
112
 
113
+ /** @internal The KeyObject identity accessors, captured at load. These are GETTERS rather than
114
+ * methods, which makes them no less replaceable and the reads no less live: `key.asymmetricKeyType`
115
+ * is a call into a function the prototype holds. What each answers is which key this IS, and that
116
+ * decides an algorithm binding, a curve, a modulus length and whether a pair corresponds, so a
117
+ * replacement answering `"rsa"` for an Ed25519 key made an import accept that key as RSA-PSS, which
118
+ * is a type confusion on the one question the import exists to settle. They sit on the shared
119
+ * parents (`KeyObject.prototype` and the asymmetric parent between it and the two key prototypes),
120
+ * so the descriptors are taken from there rather than from the leaf prototypes. */
121
+ function _getterOf(proto, name) {
122
+ for (var cur = proto; cur !== null && cur !== intrinsic.ObjectProto; cur = intrinsic.getPrototypeOf(cur)) {
123
+ var d = intrinsic.getOwnPropertyDescriptor(cur, name);
124
+ if (d !== undefined && typeof d.get === "function") return intrinsic.uncurry(d.get);
125
+ }
126
+ throw new TypeError("guard-crypto: node:crypto carries no " + name + " accessor to capture");
127
+ }
128
+ var _keyTypeGet = _getterOf(_publicProto, "asymmetricKeyType");
129
+ var _keyDetailsGet = _getterOf(_publicProto, "asymmetricKeyDetails");
130
+ var _keyKindGet = _getterOf(_publicProto, "type");
131
+ var _secretSizeGet = _getterOf(_secretProto, "symmetricKeySize");
132
+
133
+ /** @internal The AEAD transform methods, captured at load off the two prototypes. Capturing the
134
+ * CONSTRUCTION is not enough on its own: the object it returns carries its methods as ordinary
135
+ * prototype properties, so a caller reaching one through that object takes a live read. The
136
+ * authentication tag is the worst of them, because a replaced `setAuthTag` makes a decryptor
137
+ * authenticate against a tag it was never handed, which is a fail-open on the only check that says
138
+ * an AEAD message is genuine, and a replaced `getAuthTag` puts a chosen tag on the wire.
139
+ *
140
+ * `Cipheriv` and `Decipheriv` own SEPARATE copies and carry different sets: only an encryptor has
141
+ * `getAuthTag` and only a decryptor has `setAuthTag`, so the two are captured apart and a verb that
142
+ * belongs to one refuses the other rather than reaching a method that is not there. The sample
143
+ * transforms are discarded; AES-256-GCM is inside the FIPS boundary, so the load stays loadable
144
+ * under `crypto.setFips(1)` for the reason the key pair above gives. */
145
+ var _sampleKey = intrinsic.bufferAlloc(32);
146
+ var _sampleIv = intrinsic.bufferAlloc(12);
147
+ var _cipherProto = intrinsic.getPrototypeOf(_createCipheriv("aes-256-gcm", _sampleKey, _sampleIv));
148
+ var _decipherProto = intrinsic.getPrototypeOf(_createDecipheriv("aes-256-gcm", _sampleKey, _sampleIv));
149
+ var _cipherUpdate = intrinsic.uncurry(_cipherProto.update);
150
+ var _cipherFinal = intrinsic.uncurry(_cipherProto.final);
151
+ var _cipherSetAAD = intrinsic.uncurry(_cipherProto.setAAD);
152
+ var _cipherGetAuthTag = intrinsic.uncurry(_cipherProto.getAuthTag);
153
+ var _cipherSetAutoPadding = intrinsic.uncurry(_cipherProto.setAutoPadding);
154
+ var _decipherUpdate = intrinsic.uncurry(_decipherProto.update);
155
+ var _decipherFinal = intrinsic.uncurry(_decipherProto.final);
156
+ var _decipherSetAAD = intrinsic.uncurry(_decipherProto.setAAD);
157
+ var _decipherSetAuthTag = intrinsic.uncurry(_decipherProto.setAuthTag);
158
+ var _decipherSetAutoPadding = intrinsic.uncurry(_decipherProto.setAutoPadding);
159
+
160
+ /** @internal The ephemeral-agreement methods and the point conversion, captured at load for the same
161
+ * reason. Each decides an EC point, which is a public key: a replacement returns a point of its own
162
+ * choosing, and a caller that pins a key then pins the replacement's. `convertKey` is a static on
163
+ * the constructor rather than a module property, which makes it no less replaceable. */
164
+ var _ecdhProto = intrinsic.getPrototypeOf(_createECDH("prime256v1"));
165
+ var _ecdhSetPrivateKey = intrinsic.uncurry(_ecdhProto.setPrivateKey);
166
+ var _ecdhGetPublicKey = intrinsic.uncurry(_ecdhProto.getPublicKey);
167
+ var _ecdhConvertKey = nodeCrypto.ECDH.convertKey;
168
+
169
+ /** @internal Node's own WebCrypto `exportKey`, with the object it is called on, both captured at
170
+ * load. It is reached as `crypto.webcrypto.subtle.exportKey`, which is three property reads deep,
171
+ * and it returns key material. */
172
+ var _nodeSubtle = nodeCrypto.webcrypto.subtle;
173
+ var _nodeSubtleExportKey = intrinsic.uncurry(_nodeSubtle.exportKey);
174
+
77
175
  /** A signature verified through the operation captured at load. Same arguments as `crypto.verify`.
78
176
  *
79
177
  * `crypto.verify` is an ordinary writable property of the module object, and it was read once per
@@ -121,8 +219,10 @@ function sign(algorithm, data, key) {
121
219
  * replaced hash `update` cannot choose the content a message digest covers, driven through
122
220
  * `pki.cms.authenticate` and read back with `pki.cms.decrypt`.
123
221
  */
124
- function digest(name, bytes) {
125
- return _hashDigest(_hashUpdate(_createHash(name), bytes));
222
+ function digest(name, bytes, encodings) {
223
+ var inputEncoding = encodings === undefined ? undefined : encodings.input;
224
+ var outputEncoding = encodings === undefined ? undefined : encodings.output;
225
+ return _hashDigest(_hashUpdate(_createHash(name), bytes, inputEncoding), outputEncoding);
126
226
  }
127
227
 
128
228
  /** A digest over SEVERAL parts, fed in order through the operations captured at load. It is `digest`
@@ -136,12 +236,23 @@ function digest(name, bytes) {
136
236
  *
137
237
  * @enforced-by behavioral -- shares the unarmed shape `digest` below describes.
138
238
  */
139
- function digestParts(name, parts) {
140
- var h = _createHash(name);
239
+ function digestParts(name, parts, outLen) {
240
+ var h = outLen === undefined ? _createHash(name) : _createHash(name, { outputLength: outLen });
141
241
  for (var i = 0; i < parts.length; i++) _hashUpdate(h, parts[i]);
142
242
  return _hashDigest(h);
143
243
  }
144
244
 
245
+ /** A hash handle, through the construction captured at load, for a caller that feeds it in chunks and
246
+ * cannot hold the whole input. An unavailable digest name throws here, which is also how a caller
247
+ * asks whether one is available.
248
+ *
249
+ * @enforced-by guard-shape-reinlined
250
+ * @guard-shape \.createHash\s*\(
251
+ */
252
+ function hash(name, outLen) {
253
+ return outLen === undefined ? _createHash(name) : _createHash(name, { outputLength: outLen });
254
+ }
255
+
145
256
  /** An extendable-output function squeezed to `outLen` bytes, through the operations captured at load.
146
257
  * A single-stage KDF derives a key pair and the HPKE key schedule's secrets this way, so a replaced
147
258
  * `update` chooses what the derivation covers and a replaced `digest` chooses the key material itself.
@@ -164,29 +275,398 @@ function xof(name, bytes, outLen) {
164
275
  * @enforced-by behavioral -- the Hmac prototype's `update` and `digest` are ordinary writable
165
276
  * properties, with the same absence of a rename-proof shape as `digest` above. The guard is the RED
166
277
  * conformance vector over the key schedule.
278
+ *
279
+ * @enforced-by guard-shape-reinlined
280
+ * @guard-shape \.createHmac\s*\(
167
281
  */
168
282
  function hmac(name, key, bytes) {
169
283
  return _hmacDigest(_hmacUpdate(_createHmac(name, key), bytes));
170
284
  }
171
285
 
172
286
  /** A key imported through the operation captured at load. Same arguments as `crypto.createPublicKey`,
173
- * `crypto.createPrivateKey` and `crypto.createSecretKey`.
287
+ * `crypto.createPrivateKey` and `crypto.createSecretKey`. A verifier checks a signature against
288
+ * whatever key object it is handed, so an import returning another genuine key of the same family
289
+ * makes a signature made by that key verify against the material a caller pinned.
174
290
  *
175
- * @enforced-by behavioral -- the shape `nodeCrypto\.create(?:Public|Private|Secret)Key\s*\(` is
176
- * rename-proof and would catch the class anywhere, and 42 sites across 9 lib modules still reach the
177
- * module property directly on the key-agreement, KEM and key-format paths, so arming it now would fail
178
- * the gate on a clean tree. It arms with that migration. Until then the guard is the RED conformance
179
- * vector: a replaced `crypto.createPublicKey` returning another genuine key cannot substitute the key a
180
- * signature is verified against, driven through `pki.tlog.verifyNote` and `pki.key.publicFromPrivate`.
291
+ * @enforced-by guard-shape-reinlined
292
+ * @guard-shape \.createPublicKey\s*\(
181
293
  */
182
294
  function publicKey(spec) { return _createPublicKey(spec); }
183
295
 
184
- // @enforced-by behavioral -- shares the migration note on `publicKey` above; the signer's own key is
296
+ /** A private key imported through the operation captured at load. The signer's own key is chosen
297
+ * here, so a replacement signs with a key the caller never named.
298
+ *
299
+ * @enforced-by guard-shape-reinlined
300
+ * @guard-shape \.createPrivateKey\s*\(
301
+ */
185
302
  function privateKey(spec) { return _createPrivateKey(spec); }
186
303
 
187
- // @enforced-by behavioral -- shares the migration note on `publicKey` above; a MAC key substituted at
304
+ /** A raw key imported through the operation captured at load. A MAC key substituted at import makes
305
+ * a MAC verify against material the caller never supplied.
306
+ *
307
+ * @enforced-by guard-shape-reinlined
308
+ * @guard-shape \.createSecretKey\s*\(
309
+ */
188
310
  function secretKey(material) { return _createSecretKey(material); }
189
311
 
312
+ /** The static Diffie-Hellman agreement, through the operation captured at load. `crypto.diffieHellman`
313
+ * read off the module handle at call time returns the traditional half of a shared secret, so a
314
+ * replacement supplies that half outright: driving `pki.hpke.decap` with one returning a fixed buffer
315
+ * derived a secret from the value the replacement chose, and no later check recovers it, because the
316
+ * value IS the secret rather than a claim about it.
317
+ *
318
+ * @enforced-by guard-shape-reinlined
319
+ * @guard-shape (?<!guard\.crypto)\.diffieHellman\s*\(
320
+ */
321
+ function diffieHellman(spec) { return _diffieHellman(spec); }
322
+
323
+ /** A key pair, through the operation captured at load. A replacement decides the ephemeral key an
324
+ * encapsulation is made under, which is the other half of the same exchange.
325
+ *
326
+ * @enforced-by guard-shape-reinlined
327
+ * @guard-shape \.generateKeyPairSync\s*\(
328
+ */
329
+ function generateKeyPair(type, options) {
330
+ return options === undefined ? _generateKeyPairSync(type) : _generateKeyPairSync(type, options);
331
+ }
332
+
333
+ /** The ML-KEM encapsulation, through the operation captured at load. It returns the post-quantum half
334
+ * of a hybrid shared secret outright, so a replacement supplies that half.
335
+ *
336
+ * @enforced-by guard-shape-reinlined
337
+ * @guard-shape (?<!guard\.crypto)\.encapsulate\s*\(
338
+ * @guard-via compositeKem\.encapsulate\s*\(
339
+ */
340
+ function encapsulate(publicKeyObject) { return _encapsulate(publicKeyObject); }
341
+
342
+ /** The ML-KEM decapsulation, through the operation captured at load.
343
+ *
344
+ * @enforced-by guard-shape-reinlined
345
+ * @guard-shape (?<!guard\.crypto)\.decapsulate\s*\(
346
+ * @guard-via compositeKem\.decapsulate\s*\(
347
+ */
348
+ function decapsulate(privateKeyObject, enc) { return _decapsulate(privateKeyObject, enc); }
349
+
350
+ /** An AEAD encryption transform, through the construction captured at load. A replacement decides the
351
+ * cipher a seal runs under, and therefore the ciphertext and the tag.
352
+ *
353
+ * @enforced-by guard-shape-reinlined
354
+ * @guard-shape \.createCipheriv\s*\(
355
+ */
356
+ function cipher(algorithm, key, iv, options) {
357
+ return options === undefined ? _createCipheriv(algorithm, key, iv)
358
+ : _createCipheriv(algorithm, key, iv, options);
359
+ }
360
+
361
+ /** An AEAD decryption transform, through the construction captured at load.
362
+ *
363
+ * @enforced-by guard-shape-reinlined
364
+ * @guard-shape \.createDecipheriv\s*\(
365
+ */
366
+ function decipher(algorithm, key, iv, options) {
367
+ return options === undefined ? _createDecipheriv(algorithm, key, iv)
368
+ : _createDecipheriv(algorithm, key, iv, options);
369
+ }
370
+
371
+ /** Random octets, through the operation captured at load. This is where a content-encryption key, a
372
+ * MAC key, an IV, a nonce and a salt are born, so a replacement returning a value it already knows
373
+ * hands it every message those protect, and nothing downstream can tell a chosen key from a random
374
+ * one.
375
+ *
376
+ * @enforced-by guard-shape-reinlined
377
+ * @guard-shape (?<!guard\.crypto)\.randomBytes\s*\(
378
+ */
379
+ function randomBytes(n) { return _randomBytes(n); }
380
+
381
+ /** A buffer filled with random octets in place, through the operation captured at load.
382
+ *
383
+ * @enforced-by guard-shape-reinlined
384
+ * @guard-shape \.randomFillSync\s*\(
385
+ */
386
+ function randomFill(buffer) { return _randomFillSync(buffer); }
387
+
388
+ /** A random UUID, through the operation captured at load.
389
+ *
390
+ * @enforced-by guard-shape-reinlined
391
+ * @guard-shape (?<!guard\.crypto)\.randomUUID\s*\(
392
+ */
393
+ function randomUUID() { return _randomUUID(); }
394
+
395
+ /** The PBKDF2 derivation, through the operation captured at load. It decides the key-encryption key a
396
+ * password unwraps, so a replacement returning a fixed value makes every password open the message.
397
+ *
398
+ * @enforced-by guard-shape-reinlined
399
+ * @guard-shape \.pbkdf2Sync\s*\(
400
+ */
401
+ function pbkdf2(password, salt, iterations, keylen, digestName) {
402
+ return _pbkdf2Sync(password, salt, iterations, keylen, digestName);
403
+ }
404
+
405
+ /** The PBKDF2 derivation in its callback form, through the operation captured at load.
406
+ *
407
+ * @enforced-by guard-shape-reinlined
408
+ * @guard-shape (?<!guard\.crypto)\.pbkdf2\s*\(
409
+ */
410
+ function pbkdf2Async(password, salt, iterations, keylen, digestName, callback) {
411
+ return _pbkdf2(password, salt, iterations, keylen, digestName, callback);
412
+ }
413
+
414
+ /** The HKDF expand-and-extract, through the operation captured at load.
415
+ *
416
+ * @enforced-by guard-shape-reinlined
417
+ * @guard-shape \.hkdfSync\s*\(
418
+ */
419
+ function hkdf(digestName, ikm, salt, info, keylen) {
420
+ return _hkdfSync(digestName, ikm, salt, info, keylen);
421
+ }
422
+
423
+ /** The RSA public-key transform, through the operation captured at load. It decides the key-transport
424
+ * ciphertext a recipient receives, so a replacement encrypts to a key of its own choosing.
425
+ *
426
+ * @enforced-by guard-shape-reinlined
427
+ * @guard-shape (?<!guard\.crypto)\.publicEncrypt\s*\(
428
+ */
429
+ function publicEncrypt(spec, bytes) { return _publicEncrypt(spec, bytes); }
430
+
431
+ /** The RSA private-key transform, through the operation captured at load. It returns the secret a
432
+ * recipient recovers from a key-transport ciphertext, so a replacement supplies that secret.
433
+ *
434
+ * @enforced-by guard-shape-reinlined
435
+ * @guard-shape (?<!guard\.crypto)\.privateDecrypt\s*\(
436
+ */
437
+ function privateDecrypt(spec, bytes) { return _privateDecrypt(spec, bytes); }
438
+
439
+ /** An ephemeral elliptic-curve agreement, through the constructor captured at load. The object it
440
+ * returns carries its methods live, so a caller derives a point with `ecPointFromScalar` rather than
441
+ * driving this one.
442
+ *
443
+ * @enforced-by guard-shape-reinlined
444
+ * @guard-shape \.createECDH\s*\(
445
+ */
446
+ function ecdh(curveName) { return _createECDH(curveName); }
447
+
448
+ /** The EC point a scalar generates, in uncompressed SEC1 form, with the agreement built and driven
449
+ * entirely through operations captured at load. A point is a public key, so a replaced
450
+ * `setPrivateKey` or `getPublicKey` returns one of its own choosing and a caller that pins a key
451
+ * pins the replacement's.
452
+ *
453
+ * @enforced-by guard-shape-reinlined
454
+ * @guard-shape \.setPrivateKey\s*\(
455
+ */
456
+ function ecPointFromScalar(curveName, scalar) {
457
+ var handle = _createECDH(curveName);
458
+ _ecdhSetPrivateKey(handle, scalar);
459
+ return _ecdhGetPublicKey(handle, null, "uncompressed");
460
+ }
461
+
462
+ /** An EC point converted between SEC1 forms, through the static captured at load. De-compressing a
463
+ * point is also what decides it is ON the curve, so a replacement answers both questions.
464
+ *
465
+ * @enforced-by guard-shape-reinlined
466
+ * @guard-shape \.convertKey\s*\(
467
+ */
468
+ function ecConvertPoint(point, curveName, format) {
469
+ return _ecdhConvertKey(point, curveName, undefined, undefined, format);
470
+ }
471
+
472
+ /** Key material exported through NODE's own WebCrypto, reached through the operation and the receiver
473
+ * captured at load. This is the fallback for a `CryptoKey` from another implementation, and it
474
+ * returns key material, so a replacement decides those bytes.
475
+ *
476
+ * @enforced-by guard-shape-reinlined
477
+ * @guard-shape \.webcrypto\.subtle\.exportKey\s*\(
478
+ */
479
+ function nodeExportKey(format, key) { return _nodeSubtleExportKey(_nodeSubtle, format, key); }
480
+
481
+ /** @internal Which of the two transform prototypes `t` has. A verb that belongs to one direction
482
+ * refuses the other rather than reaching for a method that is not there, and the question is asked
483
+ * of the PROTOTYPE rather than with `instanceof`, which consults a `Symbol.hasInstance` the
484
+ * constructor's holder can replace. */
485
+ function _transformKind(t) {
486
+ var proto = t === null || t === undefined ? null : intrinsic.getPrototypeOf(t);
487
+ if (proto === _cipherProto) return "cipher";
488
+ if (proto === _decipherProto) return "decipher";
489
+ return null;
490
+ }
491
+
492
+ /** Bytes put through an AEAD or block transform, in either direction, through the method captured at
493
+ * load for that direction.
494
+ *
495
+ * @enforced-by behavioral -- the shape it would declare is the one `guard.secret.cipherFinish`
496
+ * already owns (an `update` paired with a `final`), and that guard is the only caller: a transform is
497
+ * driven to produce bytes that owe a wipe, so the two rules live at one door.
498
+ */
499
+ function transformUpdate(t, bytes) {
500
+ var kind = _transformKind(t);
501
+ if (kind === "cipher") return _cipherUpdate(t, bytes);
502
+ if (kind === "decipher") return _decipherUpdate(t, bytes);
503
+ throw new TypeError("guard.crypto.transformUpdate: expects a node:crypto cipher or decipher");
504
+ }
505
+
506
+ /** The trailing bytes of a transform, through the method captured at load for its direction.
507
+ *
508
+ * @enforced-by behavioral -- shares the note on `transformUpdate` above, whose pair it is.
509
+ */
510
+ function transformFinal(t) {
511
+ var kind = _transformKind(t);
512
+ if (kind === "cipher") return _cipherFinal(t);
513
+ if (kind === "decipher") return _decipherFinal(t);
514
+ throw new TypeError("guard.crypto.transformFinal: expects a node:crypto cipher or decipher");
515
+ }
516
+
517
+ /** The additional authenticated data an AEAD transform covers, in either direction. A replacement
518
+ * changes what the tag commits to without changing the tag.
519
+ *
520
+ * @enforced-by guard-shape-reinlined
521
+ * @guard-shape (?<!guard\.crypto)\.setAAD\s*\(
522
+ */
523
+ function transformSetAAD(t, aad) {
524
+ var kind = _transformKind(t);
525
+ if (kind === "cipher") return _cipherSetAAD(t, aad);
526
+ if (kind === "decipher") return _decipherSetAAD(t, aad);
527
+ throw new TypeError("guard.crypto.transformSetAAD: expects a node:crypto cipher or decipher");
528
+ }
529
+
530
+ /** Turns a transform's automatic padding off, in either direction. The key-wrap and CBC paths need
531
+ * the block boundary they computed, not one the transform adds, so a replacement that leaves padding
532
+ * on changes the block count a wrap produces.
533
+ *
534
+ * @enforced-by guard-shape-reinlined
535
+ * @guard-shape (?<!guard\.crypto)\.setAutoPadding\s*\(
536
+ */
537
+ function transformNoPadding(t) {
538
+ var kind = _transformKind(t);
539
+ if (kind === "cipher") return _cipherSetAutoPadding(t, false);
540
+ if (kind === "decipher") return _decipherSetAutoPadding(t, false);
541
+ throw new TypeError("guard.crypto.transformNoPadding: expects a node:crypto cipher or decipher");
542
+ }
543
+
544
+ /** The authentication tag an encryptor produced. Only an encryptor carries it, so a decryptor is
545
+ * refused rather than silently answering undefined, and a replacement puts a chosen tag on the wire.
546
+ *
547
+ * @enforced-by guard-shape-reinlined
548
+ * @guard-shape (?<!guard\.crypto)\.getAuthTag\s*\(
549
+ */
550
+ function cipherAuthTag(t) {
551
+ if (_transformKind(t) !== "cipher") {
552
+ throw new TypeError("guard.crypto.cipherAuthTag: expects a node:crypto cipher");
553
+ }
554
+ return _cipherGetAuthTag(t);
555
+ }
556
+
557
+ /** The authentication tag a decryptor must verify against. Only a decryptor carries it. This is the
558
+ * single check that says an AEAD message is genuine, so a replacement that discards the tag makes the
559
+ * decryptor authenticate against one it was never handed, and the message opens.
560
+ *
561
+ * @enforced-by guard-shape-reinlined
562
+ * @guard-shape (?<!guard\.crypto)\.setAuthTag\s*\(
563
+ */
564
+ function decipherSetAuthTag(t, tag) {
565
+ if (_transformKind(t) !== "decipher") {
566
+ throw new TypeError("guard.crypto.decipherSetAuthTag: expects a node:crypto decipher");
567
+ }
568
+ return _decipherSetAuthTag(t, tag);
569
+ }
570
+
571
+ /** @internal Whether `v` is a public or a private KeyObject, which are the two the asymmetric
572
+ * accessors belong to. A SECRET KeyObject is a KeyObject and is not one of them: node refuses the
573
+ * accessor outright for that receiver, so a verb that admitted all three and then reached for it
574
+ * turned a caller's wrong key kind into a raw TypeError where its module had promised a typed
575
+ * refusal. The tolerant verbs below ask this rather than `isKeyObject`. */
576
+ function _isAsymmetricKeyObject(v) {
577
+ var proto = v === null || v === undefined ? null : intrinsic.getPrototypeOf(v);
578
+ return proto === _publicProto || proto === _privateProto;
579
+ }
580
+
581
+ /** The algorithm family of `v` when `v` is an asymmetric KeyObject, and `undefined` for anything
582
+ * else, a secret key included. The call sites that ask this are deciding whether a caller handed them
583
+ * an asymmetric key at all, and the duck-typed form they asked it with (`typeof v === "object" &&
584
+ * v.asymmetricKeyType != null`) is satisfied by a plain object carrying that one field, so a forged
585
+ * object passed as a key and was then used as one. Asking the prototype first settles both questions
586
+ * at once, and a secret key answers `undefined` here exactly as the accessor itself did.
587
+ *
588
+ * @enforced-by behavioral -- the shape is `keyType`'s, which is declared on it below; this is the
589
+ * tolerant door onto the same accessor, and the RED conformance vector drives a forged object and a
590
+ * secret key through the verbs that used to accept them.
591
+ */
592
+ function keyTypeOf(v) { return _isAsymmetricKeyObject(v) ? _keyTypeGet(v) : undefined; }
593
+
594
+ /** Whether `v` is "public", "private" or "secret" when it IS a KeyObject, and `undefined` otherwise.
595
+ *
596
+ * @enforced-by behavioral -- shares the note on `keyTypeOf` above.
597
+ */
598
+ function keyKindOf(v) { return isKeyObject(v) ? _keyKindGet(v) : undefined; }
599
+
600
+ /** A key's algorithm parameters when `v` is an asymmetric KeyObject, and `undefined` for anything
601
+ * else, a secret key included.
602
+ *
603
+ * @enforced-by behavioral -- shares the note on `keyTypeOf` above.
604
+ */
605
+ function keyDetailsOf(v) { return _isAsymmetricKeyObject(v) ? _keyDetailsGet(v) : undefined; }
606
+
607
+ /** Which algorithm family a key belongs to ("ed25519", "rsa", "rsa-pss", "ec", "x25519", ...), read
608
+ * through the accessor captured at load. This is the one question an import exists to settle, and it
609
+ * decides which algorithm a signature is checked under, so a replacement answering `"rsa"` for an
610
+ * Ed25519 key made an import accept it as RSA-PSS.
611
+ *
612
+ * @enforced-by guard-shape-reinlined
613
+ * @guard-shape (?<!guard\.crypto)\.asymmetricKeyType\b
614
+ */
615
+ function keyType(keyObject) {
616
+ if (!_isAsymmetricKeyObject(keyObject)) {
617
+ throw new TypeError("guard.crypto.keyType: expects a node:crypto public or private KeyObject");
618
+ }
619
+ return _keyTypeGet(keyObject);
620
+ }
621
+
622
+ /** A key's algorithm parameters (`modulusLength`, `namedCurve`, `hashAlgorithm`, ...), read through
623
+ * the accessor captured at load. A modulus length and a curve name are both checks a caller pinned.
624
+ *
625
+ * @enforced-by guard-shape-reinlined
626
+ * @guard-shape (?<!guard\.crypto)\.asymmetricKeyDetails\b
627
+ */
628
+ function keyDetails(keyObject) {
629
+ if (!_isAsymmetricKeyObject(keyObject)) {
630
+ throw new TypeError("guard.crypto.keyDetails: expects a node:crypto public or private KeyObject");
631
+ }
632
+ return _keyDetailsGet(keyObject);
633
+ }
634
+
635
+ /** Whether a key is "public", "private" or "secret", read through the accessor captured at load. A
636
+ * signer that accepts a public key where it needed a private one, or the reverse, is deciding on this.
637
+ *
638
+ * @enforced-by behavioral -- `.type` is the most common field name in the toolkit, carried by every
639
+ * parsed ASN.1 node and every algorithm descriptor, so a shape matching it would fire on hundreds of
640
+ * sites that are not key objects at all. The guard is the RED conformance vector over the import.
641
+ */
642
+ function keyKind(keyObject) { return _keyKindGet(keyObject); }
643
+
644
+ /** A raw key's length in bits, read through the accessor captured at load.
645
+ *
646
+ * @enforced-by guard-shape-reinlined
647
+ * @guard-shape (?<!guard\.crypto)\.symmetricKeySize\b
648
+ */
649
+ function secretKeySize(keyObject) {
650
+ var proto = keyObject === null || keyObject === undefined ? null : intrinsic.getPrototypeOf(keyObject);
651
+ if (proto !== _secretProto) {
652
+ throw new TypeError("guard.crypto.secretKeySize: expects a node:crypto secret KeyObject");
653
+ }
654
+ return _secretSizeGet(keyObject);
655
+ }
656
+
657
+ /** Whether `v` is one of node's three KeyObject kinds, asked of its PROTOTYPE. `v instanceof
658
+ * crypto.KeyObject` reads the constructor off the module object and then consults a
659
+ * `Symbol.hasInstance` either side can replace, so the answer is taken from the prototypes this
660
+ * module captured at load instead.
661
+ *
662
+ * @enforced-by guard-shape-reinlined
663
+ * @guard-shape instanceof\s+(?:nodeCrypto|crypto)\.KeyObject
664
+ */
665
+ function isKeyObject(v) {
666
+ var proto = v === null || v === undefined ? null : intrinsic.getPrototypeOf(v);
667
+ return proto === _publicProto || proto === _privateProto || proto === _secretProto;
668
+ }
669
+
190
670
  /** A KeyObject exported through the operation captured at load. `keyObject.export(spec)` reaches the
191
671
  * method off the live prototype, so a replacement decides the bytes a caller is handed: one exporting
192
672
  * a fixed value made two distinct authorized TUF keys carry the same material identifier, which took a
@@ -224,7 +704,19 @@ function assertOctetAligned(bitString, E, code, label) {
224
704
  }
225
705
 
226
706
  module.exports = _freeze({ constantTimeEqual: constantTimeEqual, digest: digest,
227
- digestParts: digestParts, xof: xof, hmac: hmac, verify: verify, sign: sign,
707
+ digestParts: digestParts, xof: xof, hash: hash, hmac: hmac, verify: verify, sign: sign,
228
708
  publicKey: publicKey, privateKey: privateKey, secretKey: secretKey, exportKey: exportKey,
709
+ diffieHellman: diffieHellman, generateKeyPair: generateKeyPair,
710
+ encapsulate: encapsulate, decapsulate: decapsulate, cipher: cipher, decipher: decipher,
711
+ randomBytes: randomBytes, randomFill: randomFill, randomUUID: randomUUID,
712
+ pbkdf2: pbkdf2, pbkdf2Async: pbkdf2Async, hkdf: hkdf,
713
+ publicEncrypt: publicEncrypt, privateDecrypt: privateDecrypt,
714
+ ecdh: ecdh, ecPointFromScalar: ecPointFromScalar,
715
+ ecConvertPoint: ecConvertPoint, nodeExportKey: nodeExportKey, isKeyObject: isKeyObject,
716
+ keyType: keyType, keyDetails: keyDetails, keyKind: keyKind, secretKeySize: secretKeySize,
717
+ keyTypeOf: keyTypeOf, keyKindOf: keyKindOf, keyDetailsOf: keyDetailsOf,
718
+ transformUpdate: transformUpdate, transformFinal: transformFinal,
719
+ transformSetAAD: transformSetAAD, transformNoPadding: transformNoPadding,
720
+ cipherAuthTag: cipherAuthTag, decipherSetAuthTag: decipherSetAuthTag,
229
721
  padding: padding, saltLength: saltLength,
230
722
  isOctetAligned: isOctetAligned, assertOctetAligned: assertOctetAligned });
package/lib/guard-der.js CHANGED
@@ -9,6 +9,7 @@ var _sizeOf = require("./guard-intrinsic").sizeOf;
9
9
  var _create = require("./guard-intrinsic").create;
10
10
  var _isBuffer = require("./guard-intrinsic").isBuffer;
11
11
  var _isArray = require("./guard-intrinsic").isArray;
12
+ var _append = require("./guard-intrinsic").append;
12
13
 
13
14
  var asn1 = null;
14
15
  function _asn1() { if (asn1 === null) asn1 = require("./asn1-der"); return asn1; }
@@ -117,7 +118,11 @@ function _element(node, E, code, label) {
117
118
  throw E(code, label + " of universal constructed type " + tag + " has no strict DER structure validator here");
118
119
  }
119
120
  var n = kids.length, members = [];
120
- for (var i = 0; i < n; i++) members[i] = _element(kids[i], E, code, label);
121
+ /** @internal Appended by defining the index. A store at an index the list has no own property at
122
+ * consults a setter inherited from the array prototype, and the SET ordering below is checked
123
+ * over this list, so a member read back through such a hole is one the canonical-order check
124
+ * never saw. */
125
+ for (var i = 0; i < n; i++) _append(members, _element(kids[i], E, code, label));
121
126
  if (cls === "universal" && tag === C.SET && !setOrderOk(members)) {
122
127
  throw E(code, label + " has a SET whose members are in no canonical DER order (X.690 sec. 11.6 / X.680 sec. 8.6)");
123
128
  }
@@ -528,14 +528,24 @@ var _arrSort = uncurry(Array.prototype.sort);
528
528
  var _arrConcat = uncurry(Array.prototype.concat);
529
529
  var _arrSlice = uncurry(Array.prototype.slice);
530
530
  var _arrJoin = uncurry(Array.prototype.join);
531
- var _arrPush = uncurry(Array.prototype.push);
531
+ /** @internal `push` is NOT captured and NOT offered. Capturing it closes who `push` is, not what
532
+ * `push` DOES: it STORES at the index, and a store walks the prototype chain for a setter, so an
533
+ * accessor installed at an array index receives each element as it is appended and can define
534
+ * something else in its place. Measured through `pki.asn1.read.oid`: the content octets of `1.2.3`
535
+ * rendered `0.1.3` through a captured push. `append` below defines the index on the array itself,
536
+ * and `concatList` / `copyList` / `selectList` / `mapList` build their results the same way. With
537
+ * nothing to reach for, no module in lib/ can take the storing form. */
532
538
  /** @internal The mutators. A list is what a rule is enforced over, so an operation that drops or moves
533
539
  * an element decides whether the rule reaches it: a replaced `pop` that popped twice took a signed
534
540
  * note's last signature line away with the empty tail element, and the forged signature on that line
535
541
  * was never checked. */
542
+ /** @internal `unshift` is absent for the reason `push` is: it GROWS the list, so it stores at an
543
+ * index the array has no own property at, and a store walks the prototype chain for a setter. The
544
+ * mutators kept below move or drop elements that already have own slots, which reaches no accessor
545
+ * on a list this toolkit built by defining. A module prepending to a list counts its elements and
546
+ * appends them in order instead; `encodeLength` and `intToDer` in lib/asn1-der.js are the pattern. */
536
547
  var _arrPop = uncurry(Array.prototype.pop);
537
548
  var _arrShift = uncurry(Array.prototype.shift);
538
- var _arrUnshift = uncurry(Array.prototype.unshift);
539
549
  var _arrSplice = uncurry(Array.prototype.splice);
540
550
  var _arrReverse = uncurry(Array.prototype.reverse);
541
551
 
@@ -706,10 +716,8 @@ module.exports = Object.freeze({
706
716
  min: _mathMin,
707
717
  max: _mathMax,
708
718
  parseInt: _parseInt,
709
- push: _arrPush,
710
719
  pop: _arrPop,
711
720
  shift: _arrShift,
712
- unshift: _arrUnshift,
713
721
  splice: _arrSplice,
714
722
  reverse: _arrReverse,
715
723
  toUpperCase: _strToUpperCase,