@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
@@ -23,7 +23,6 @@
23
23
  var asn1 = require("./asn1-der");
24
24
  var oid = require("./oid");
25
25
  var webcrypto = require("./webcrypto");
26
- var nodeCrypto = require("node:crypto");
27
26
  var frameworkError = require("./framework-error");
28
27
  var guard = require("./guard-all");
29
28
  var intrinsic = require("./guard-intrinsic");
@@ -115,11 +114,11 @@ function _mlkemDecaps(d, seed, mlkemCT) {
115
114
  function _ecPubFromPoint(d, point) {
116
115
  if (point.length < 1 || point[0] !== 0x04) throw _err("kem/bad-key", "the EC component point is not in uncompressed form");
117
116
  var spki = _b.sequence([_b.sequence([_b.oid(oid.byName("ecPublicKey")), _b.oid(oid.byName(d.trad.curve))]), _b.bitString(point, 0)]);
118
- return nodeCrypto.createPublicKey({ key: spki, format: "der", type: "spki" });
117
+ return guard.crypto.publicKey({ key: spki, format: "der", type: "spki" });
119
118
  }
120
119
  function _okpPubFromRaw(d, raw) {
121
120
  var spki = _b.sequence([_b.sequence([_b.oid(oid.byName(d.trad.curve))]), _b.bitString(raw, 0)]);
122
- return nodeCrypto.createPublicKey({ key: spki, format: "der", type: "spki" });
121
+ return guard.crypto.publicKey({ key: spki, format: "der", type: "spki" });
123
122
  }
124
123
  /** @internal The encoding is this helper's own allocation and holds the traditional private scalar, so
125
124
  * it is cleared here. A caller's own cleanup cannot reach a buffer it never sees, and both the
@@ -127,13 +126,13 @@ function _okpPubFromRaw(d, raw) {
127
126
  function _okpPrivFromRaw(d, raw) {
128
127
  var p8 = _b.sequence([_b.integer(0n), _b.sequence([_b.oid(oid.byName(d.trad.curve))]), _b.octetString(_b.octetString(raw))]);
129
128
  try {
130
- return nodeCrypto.createPrivateKey({ key: p8, format: "der", type: "pkcs8" });
129
+ return guard.crypto.privateKey({ key: p8, format: "der", type: "pkcs8" });
131
130
  } finally {
132
131
  guard.secret.zeroize(p8, KemError, "kem/bad-input", "the " + d.trad.curve + " component key encoding");
133
132
  }
134
133
  }
135
134
  function _rawPubOf(keyObject) {
136
- var spki = keyObject.export({ format: "der", type: "spki" });
135
+ var spki = guard.crypto.exportKey(keyObject, { format: "der", type: "spki" });
137
136
  return Buffer.from(asn1.read.bitString(asn1.decode(spki).children[1]).bytes);
138
137
  }
139
138
 
@@ -143,12 +142,12 @@ function _tradEncaps(d, tradPK) {
143
142
  var pub;
144
143
  try {
145
144
  asn1.decode(tradPK);
146
- pub = nodeCrypto.createPublicKey({ key: tradPK, format: "der", type: "pkcs1" });
145
+ pub = guard.crypto.publicKey({ key: tradPK, format: "der", type: "pkcs1" });
147
146
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component public key is not a valid RSAPublicKey", e)); }
148
- if (pub.asymmetricKeyDetails.modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
149
- var ss = Buffer.from(nodeCrypto.randomBytes(RSA_SS));
147
+ if (guard.crypto.keyDetails(pub).modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
148
+ var ss = Buffer.from(guard.crypto.randomBytes(RSA_SS));
150
149
  var ct;
151
- try { ct = Buffer.from(nodeCrypto.publicEncrypt({ key: pub, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, ss)); }
150
+ try { ct = Buffer.from(guard.crypto.publicEncrypt({ key: pub, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, ss)); }
152
151
  catch (e) {
153
152
  guard.secret.zeroize(ss, KemError, "kem/bad-input", "the RSA-OAEP component secret");
154
153
  return _promiseReject(_Promise, _err("kem/bad-key", "the RSA-OAEP component encryption failed", e));
@@ -158,8 +157,8 @@ function _tradEncaps(d, tradPK) {
158
157
  var dh, dhCt;
159
158
  try {
160
159
  var recip = trad.kind === "ec" ? _ecPubFromPoint(d, tradPK) : _okpPubFromRaw(d, tradPK);
161
- var eph = trad.kind === "ec" ? nodeCrypto.generateKeyPairSync("ec", { namedCurve: trad.node }) : nodeCrypto.generateKeyPairSync(trad.curve.toLowerCase());
162
- dh = Buffer.from(nodeCrypto.diffieHellman({ privateKey: eph.privateKey, publicKey: recip }));
160
+ var eph = trad.kind === "ec" ? guard.crypto.generateKeyPair("ec", { namedCurve: trad.node }) : guard.crypto.generateKeyPair(trad.curve.toLowerCase());
161
+ dh = Buffer.from(guard.crypto.diffieHellman({ privateKey: eph.privateKey, publicKey: recip }));
163
162
  dhCt = _rawPubOf(eph.publicKey);
164
163
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the " + trad.curve + " public key is invalid", e)); }
165
164
  return _promiseResolve(_Promise, { ss: dh, ct: dhCt });
@@ -171,37 +170,38 @@ function _tradDecaps(d, tradSK, tradCT) {
171
170
  var priv;
172
171
  try {
173
172
  asn1.decode(tradSK);
174
- priv = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "pkcs1" });
173
+ priv = guard.crypto.privateKey({ key: tradSK, format: "der", type: "pkcs1" });
175
174
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component private key is not a valid RSAPrivateKey", e)); }
176
- if (priv.asymmetricKeyDetails.modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
175
+ if (guard.crypto.keyDetails(priv).modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
177
176
  var ss;
178
- try { ss = Buffer.from(nodeCrypto.privateDecrypt({ key: priv, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, tradCT)); }
177
+ try { ss = Buffer.from(guard.crypto.privateDecrypt({ key: priv, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, tradCT)); }
179
178
  catch (_e) { return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the RSA-OAEP component decryption failed")); }
180
179
  if (ss.length !== RSA_SS) {
181
180
  guard.secret.zeroize(ss, KemError, "kem/bad-input", "the RSA-OAEP component secret");
182
181
  return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the RSA-OAEP component decryption failed"));
183
182
  }
184
- return _promiseResolve(_Promise, { ss: ss, tradPK: Buffer.from(nodeCrypto.createPublicKey(priv).export({ format: "der", type: "pkcs1" })) });
183
+ return _promiseResolve(_Promise, { ss: ss,
184
+ tradPK: Buffer.from(guard.crypto.exportKey(guard.crypto.publicKey(priv), { format: "der", type: "pkcs1" })) });
185
185
  }
186
186
  var priv2, eph;
187
187
  try {
188
188
  if (trad.kind === "ec") {
189
189
  asn1.decode(tradSK);
190
- priv2 = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "sec1" });
190
+ priv2 = guard.crypto.privateKey({ key: tradSK, format: "der", type: "sec1" });
191
191
  } else {
192
192
  priv2 = _okpPrivFromRaw(d, tradSK);
193
193
  }
194
194
  eph = trad.kind === "ec" ? _ecPubFromPoint(d, tradCT) : _okpPubFromRaw(d, tradCT);
195
195
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the " + trad.curve + " key material is invalid", e)); }
196
196
  var dh;
197
- try { dh = Buffer.from(nodeCrypto.diffieHellman({ privateKey: priv2, publicKey: eph })); }
197
+ try { dh = Buffer.from(guard.crypto.diffieHellman({ privateKey: priv2, publicKey: eph })); }
198
198
  catch (e) { return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the " + trad.curve + " Diffie-Hellman failed", e)); }
199
199
  /** @internal The same canonical point the derivation states, read from the one function that spells
200
200
  * it. The combiner hashes these bytes, so a stored spelling here and a generated one there would
201
201
  * reach different secrets from the two sides of one key. */
202
202
  var tradPK;
203
203
  try {
204
- tradPK = trad.kind === "ec" ? _ecPointOf(d, tradSK) : _rawPubOf(nodeCrypto.createPublicKey(priv2));
204
+ tradPK = trad.kind === "ec" ? _ecPointOf(d, tradSK) : _rawPubOf(guard.crypto.publicKey(priv2));
205
205
  } catch (e) {
206
206
  /** @internal The agreement already produced a secret, and this rejection happens after it, so the
207
207
  * secret is wiped here: the caller's settle-or-wipe covers a value it was handed, and a rejected
@@ -371,9 +371,7 @@ function _ecPointOf(d, tradSK) {
371
371
  var scalar = _ecScalarOf(d, tradSK);
372
372
  var point;
373
373
  try {
374
- var ecdh = nodeCrypto.createECDH(d.trad.node);
375
- ecdh.setPrivateKey(scalar);
376
- point = ecdh.getPublicKey(null, "uncompressed");
374
+ point = guard.crypto.ecPointFromScalar(d.trad.node, scalar);
377
375
  } catch (e) {
378
376
  if (e instanceof KemError) throw e;
379
377
  throw _err("kem/bad-key", "the EC component scalar does not generate a point on " + d.trad.node, e);
@@ -418,18 +416,18 @@ function _tradPubOf(d, tradSK) {
418
416
  var rp;
419
417
  try {
420
418
  asn1.decode(tradSK);
421
- rp = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "pkcs1" });
419
+ rp = guard.crypto.privateKey({ key: tradSK, format: "der", type: "pkcs1" });
422
420
  } catch (e) { throw _err("kem/bad-key", "the RSA component private key is not a valid RSAPrivateKey", e); }
423
- if (rp.asymmetricKeyDetails.modulusLength !== trad.bits) {
421
+ if (guard.crypto.keyDetails(rp).modulusLength !== trad.bits) {
424
422
  throw _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)");
425
423
  }
426
- return Buffer.from(nodeCrypto.createPublicKey(rp).export({ format: "der", type: "pkcs1" }));
424
+ return Buffer.from(guard.crypto.exportKey(guard.crypto.publicKey(rp), { format: "der", type: "pkcs1" }));
427
425
  }
428
426
  var priv;
429
427
  try {
430
428
  if (trad.kind === "ec") {
431
429
  asn1.decode(tradSK);
432
- priv = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "sec1" });
430
+ priv = guard.crypto.privateKey({ key: tradSK, format: "der", type: "sec1" });
433
431
  } else {
434
432
  priv = _okpPrivFromRaw(d, tradSK);
435
433
  }
@@ -439,7 +437,8 @@ function _tradPubOf(d, tradSK) {
439
437
  * public key nothing can use, so the two are held to each other here. Decapsulation reaches the same
440
438
  * conclusion by failing the agreement; a derivation performs no operation that would notice. */
441
439
  if (trad.kind === "ec") {
442
- var named = priv.asymmetricKeyDetails && priv.asymmetricKeyDetails.namedCurve;
440
+ var privDetails = guard.crypto.keyDetails(priv);
441
+ var named = privDetails && privDetails.namedCurve;
443
442
  if (named !== trad.node) {
444
443
  throw _err("kem/bad-key", "the EC component is on " + guard.text.showValue(named) + ", and " + d.name + " names " + trad.node);
445
444
  }
@@ -450,7 +449,7 @@ function _tradPubOf(d, tradSK) {
450
449
  * point stored beside it cannot stand in for one it does not generate. */
451
450
  return _ecPointOf(d, tradSK);
452
451
  }
453
- return _rawPubOf(nodeCrypto.createPublicKey(priv));
452
+ return _rawPubOf(guard.crypto.publicKey(priv));
454
453
  }
455
454
 
456
455
  /** @internal The composite `SubjectPublicKeyInfo` for a composite ML-KEM private key. The runtime key
@@ -488,8 +487,8 @@ async function _publicFromPrivate(privateKey) {
488
487
  * copy of the seed and is registered as one. */
489
488
  var seedPkcs8 = _mlkemSeedPkcs8(d, seed);
490
489
  guard.list.append(secrets, seedPkcs8);
491
- var mlPriv = nodeCrypto.createPrivateKey({ key: seedPkcs8, format: "der", type: "pkcs8" });
492
- ek = _rawPubOf(nodeCrypto.createPublicKey(mlPriv));
490
+ var mlPriv = guard.crypto.privateKey({ key: seedPkcs8, format: "der", type: "pkcs8" });
491
+ ek = _rawPubOf(guard.crypto.publicKey(mlPriv));
493
492
  } catch (e) {
494
493
  if (e instanceof KemError) throw e;
495
494
  throw _err("kem/bad-key", "the ML-KEM component private key is invalid", e);
package/lib/crl-sign.js CHANGED
@@ -24,6 +24,9 @@ var x509Schema = require("./schema-x509");
24
24
  var signScheme = require("./sign-scheme");
25
25
  var guard = require("./guard-all");
26
26
  var intrinsic = require("./guard-intrinsic");
27
+ /** @internal The append every list here is built with: `push` stores at the index and a store
28
+ * consults a setter inherited there, and these lists become the bytes that get signed. */
29
+ var _push = intrinsic.append;
27
30
  var _hasOwn = intrinsic.hasOwn, _bufferEquals = intrinsic.bufferEquals;
28
31
  var _arrSlice = intrinsic.arraySlice, _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
29
32
  /** @internal The RECEIVER for the captured `Promise.resolve`, captured too. `resolve` builds through
@@ -184,11 +187,11 @@ function _idpValue(idp) {
184
187
  if (idp.fullName != null) {
185
188
  var entries = Array.isArray(idp.fullName) ? pkiBuild.reqDenseArray(idp.fullName, "issuingDistributionPoint.fullName", _err, "crl/bad-idp") : [idp.fullName];
186
189
  if (!entries.length) throw _err("crl/bad-idp", "issuingDistributionPoint fullName must carry at least one GeneralName");
187
- children.push(b.contextConstructed(0, b.contextConstructed(0, Buffer.concat(entries.map(_encodeGeneralName)))));
190
+ _push(children,b.contextConstructed(0, b.contextConstructed(0, Buffer.concat(entries.map(_encodeGeneralName)))));
188
191
  }
189
192
  var scopeTrue = 0;
190
- if (idp.onlyContainsUserCerts === true) { children.push(b.contextPrimitive(1, Buffer.from([0xff]))); scopeTrue++; }
191
- if (idp.onlyContainsCACerts === true) { children.push(b.contextPrimitive(2, Buffer.from([0xff]))); scopeTrue++; }
193
+ if (idp.onlyContainsUserCerts === true) { _push(children,b.contextPrimitive(1, Buffer.from([0xff]))); scopeTrue++; }
194
+ if (idp.onlyContainsCACerts === true) { _push(children,b.contextPrimitive(2, Buffer.from([0xff]))); scopeTrue++; }
192
195
  if (idp.indirectCRL === true) throw _err("crl/bad-idp", _INDIRECT_IDP_DEFERRED);
193
196
  if (scopeTrue > 1) throw _err("crl/bad-idp", "at most one of onlyContainsUserCerts / onlyContainsCACerts may be TRUE (RFC 5280 sec. 5.2.5)");
194
197
  if (!children.length) throw _err("crl/bad-idp", "issuingDistributionPoint MUST NOT be empty (RFC 5280 sec. 5.2.5)");
@@ -232,7 +235,7 @@ function _buildCrlExtensions(spec, ctx) {
232
235
  var id = O(oidName);
233
236
  if (seen[id]) throw _err("crl/bad-input", "duplicate CRL extension " + oidName + " (RFC 5280 sec. 5.2 -- at most one instance)");
234
237
  seen[id] = true;
235
- out.push(_ext(id, critical, valueDer));
238
+ _push(out,_ext(id, critical, valueDer));
236
239
  }
237
240
  var crlNumberVal = null;
238
241
  if (spec.crlNumber != null) { var cn = _boundedInteger(spec.crlNumber, "cRLNumber"); crlNumberVal = cn.value; push("cRLNumber", false, cn.tlv); }
@@ -264,7 +267,7 @@ function _buildCrlExtensions(spec, ctx) {
264
267
  }
265
268
  _assertExtensionValueDecodes(node, extnId, "extension");
266
269
  if (extnId === O("deltaCRLIndicator")) isDelta = true;
267
- out.push(b.raw(der));
270
+ _push(out,b.raw(der));
268
271
  });
269
272
  if (isDelta) {
270
273
  if (seen[O("freshestCRL")]) throw _err("crl/bad-input", "freshestCRL MUST NOT appear in a delta CRL (RFC 5280 sec. 5.2.6)");
@@ -323,7 +326,7 @@ function _buildRevoked(entryList, isDelta) {
323
326
  var id = O(oidName);
324
327
  if (seen[id]) throw _err("crl/bad-input", "duplicate entry extension " + oidName + " in revoked entry [" + idx + "]");
325
328
  seen[id] = true;
326
- entryExts.push(_ext(id, critical, valueDer));
329
+ _push(entryExts,_ext(id, critical, valueDer));
327
330
  }
328
331
  if (e.reason != null) {
329
332
  var codeNum = _resolveReason(e.reason, isDelta);
@@ -360,10 +363,10 @@ function _buildRevoked(entryList, isDelta) {
360
363
  }
361
364
  }
362
365
  _assertExtensionValueDecodes(xnode, extnId, "entry extension");
363
- entryExts.push(b.raw(der));
366
+ _push(entryExts,b.raw(der));
364
367
  });
365
368
  }
366
- if (entryExts.length) { anyExt = true; children.push(b.sequence(entryExts)); }
369
+ if (entryExts.length) { anyExt = true; _push(children,b.sequence(entryExts)); }
367
370
  return b.sequence(children);
368
371
  });
369
372
  return { entries: entries, anyExt: anyExt };
@@ -375,7 +378,11 @@ function _parseIssuerCert(cert) {
375
378
  }
376
379
 
377
380
  function _assertIssuerCanSignCrl(issuerCert) {
378
- var kuExt = (issuerCert.extensions || []).filter(function (e) { return e.oid === O("keyUsage"); })[0];
381
+ /** @internal The selection returns the first matching row or null. `filter(...)[0]` indexes a
382
+ * result that is EMPTY when the certificate carries no keyUsage, and index 0 of an empty array
383
+ * answers from the array prototype, so a value installed there would be decoded as the issuer's
384
+ * key usage and decide whether it may sign this CRL. */
385
+ var kuExt = guard.list.firstMatch(issuerCert.extensions || [], function (e) { return e.oid === O("keyUsage"); });
379
386
  if (!kuExt) return;
380
387
  var ku;
381
388
  try { ku = EXT_DECODERS[O("keyUsage")](kuExt.value); }
@@ -453,13 +460,13 @@ function _sign(spec, issuer, opts) {
453
460
  * into the PreTBSCertList the alternative signature covers. */
454
461
  function tbsOver(extList, omitSignatureAlg) {
455
462
  var tbsChildren = [];
456
- if (version === 2) tbsChildren.push(b.integer(1n));
457
- if (omitSignatureAlg !== true) tbsChildren.push(scheme.sigAlgId);
458
- tbsChildren.push(issuerDer);
459
- tbsChildren.push(thisU);
460
- if (nextU) tbsChildren.push(nextU);
461
- if (revoked.entries.length) tbsChildren.push(b.sequence(revoked.entries));
462
- if (extList.length) tbsChildren.push(b.explicit(0, b.sequence(extList)));
463
+ if (version === 2) _push(tbsChildren,b.integer(1n));
464
+ if (omitSignatureAlg !== true) _push(tbsChildren,scheme.sigAlgId);
465
+ _push(tbsChildren,issuerDer);
466
+ _push(tbsChildren,thisU);
467
+ if (nextU) _push(tbsChildren,nextU);
468
+ if (revoked.entries.length) _push(tbsChildren,b.sequence(revoked.entries));
469
+ if (extList.length) _push(tbsChildren,b.explicit(0, b.sequence(extList)));
463
470
  return b.sequence(tbsChildren);
464
471
  }
465
472
 
@@ -813,7 +820,7 @@ function isRevoked(crl, serialNumber, opts) {
813
820
 
814
821
  function _findExtOid(list, name) {
815
822
  var want = O(name);
816
- return (list || []).filter(function (e) { return e.oid === want; })[0] || null;
823
+ return guard.list.firstMatch(list || [], function (e) { return e.oid === want; });
817
824
  }
818
825
 
819
826
  var _IDP_SCHEMA = pkix.issuingDistributionPoint("crl/scope-not-authoritative");
package/lib/crmf-sign.js CHANGED
@@ -17,12 +17,6 @@
17
17
  * @card Build a CRMF CertReqMessages with a signature proof of possession.
18
18
  */
19
19
 
20
- var nodeCrypto = require("node:crypto");
21
- /** @internal Bound at module load, like every other capture here: the proof below decides what it
22
- * agrees and what it hashes, so a replacement swapped in afterwards must not be able to steer it. */
23
- var _diffieHellman = nodeCrypto.diffieHellman;
24
- var _createPublicKey = nodeCrypto.createPublicKey;
25
- var _createPrivateKey = nodeCrypto.createPrivateKey;
26
20
  var asn1 = require("./asn1-der");
27
21
  var oid = require("./oid");
28
22
  var x509 = require("./schema-x509");
@@ -345,7 +339,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
345
339
  _assertAgreementExponent(pkcs3, "the authority certificate's key");
346
340
  }
347
341
  }
348
- try { caPub = _createPublicKey({ key: caSpkiBytes, format: "der", type: "spki" }); }
342
+ try { caPub = guard.crypto.publicKey({ key: caSpkiBytes, format: "der", type: "spki" }); }
349
343
  catch (e) { throw _err("crmf/bad-popo", "the authority certificate does not carry a key this runtime can agree with", e); }
350
344
  /** @internal The snapshot of the caller's key is this function's own copy of private material, so it
351
345
  * is registered for the wipe below rather than left to the argument boundary, which clears what it
@@ -357,7 +351,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
357
351
  /** @internal Inside the cleanup scope, because the import can throw AFTER the snapshot exists: a
358
352
  * catch that returned from out here would leave that copy of private material behind. */
359
353
  try {
360
- if (pop.key && typeof pop.key === "object" && pop.key.asymmetricKeyType != null) {
354
+ if (guard.crypto.keyTypeOf(pop.key) != null) {
361
355
  eePriv = pop.key;
362
356
  } else if (pop.key && typeof pop.key === "object" && pop.key.type === "private" &&
363
357
  typeof pop.key.export === "function") {
@@ -366,10 +360,10 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
366
360
  * applies here: supporting the encoding for a caller holding bytes and refusing the caller
367
361
  * holding the key those bytes import to would be the same key admitted one way. The export
368
362
  * is this function's own copy of private material and is cleared with the rest. */
369
- keySnapshot = pop.key.export({ format: "der", type: "pkcs8" });
363
+ keySnapshot = guard.crypto.exportKey(pop.key, { format: "der", type: "pkcs8" });
370
364
  translated = _x942PrivToPkcs3(keySnapshot);
371
365
  eePriv = translated !== null
372
- ? _createPrivateKey({ key: translated, format: "der", type: "pkcs8" })
366
+ ? guard.crypto.privateKey({ key: translated, format: "der", type: "pkcs8" })
373
367
  : pop.key;
374
368
  } else if (guard.bytes.isByteSource(pop.key)) {
375
369
  keySnapshot = guard.bytes.snapshotSource(pop.key, CrmfError, "crmf/bad-popo", "the requester's private key");
@@ -377,7 +371,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
377
371
  * copy of the private value, and an import that throws after it exists must not leave it
378
372
  * behind. The wipe below clears whatever was made, on every way out. */
379
373
  translated = _x942PrivToPkcs3(keySnapshot);
380
- eePriv = _createPrivateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
374
+ eePriv = guard.crypto.privateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
381
375
  } else {
382
376
  /** @internal A PEM key reaches the same conversion: it is the same key in the same encoding
383
377
  * with an armor around it, so admitting one form and not the other would support X9.42 for a
@@ -386,9 +380,9 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
386
380
  if (pemDer !== null) {
387
381
  keySnapshot = pemDer;
388
382
  translated = _x942PrivToPkcs3(keySnapshot);
389
- eePriv = _createPrivateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
383
+ eePriv = guard.crypto.privateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
390
384
  } else {
391
- eePriv = _createPrivateKey(pop.key);
385
+ eePriv = guard.crypto.privateKey(pop.key);
392
386
  }
393
387
  }
394
388
  } catch (e) {
@@ -402,7 +396,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
402
396
  * something this request never asked to have certified. The encryptedKey arm holds its enclosed
403
397
  * key to the same rule. */
404
398
  var eeSpki;
405
- try { eeSpki = _createPublicKey(eePriv).export({ format: "der", type: "spki" }); }
399
+ try { eeSpki = guard.crypto.exportKey(guard.crypto.publicKey(eePriv), { format: "der", type: "spki" }); }
406
400
  catch (e) { throw _err("crmf/bad-popo", "the public half of pop.key could not be derived to check it against the requested key", e); }
407
401
  /** @internal Compared as keys, not as bytes. A PKCS#3 DHParameter carries an optional
408
402
  * privateValueLength, so one finite-field key has more than one valid SubjectPublicKeyInfo and a
@@ -449,7 +443,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
449
443
  * with parameters g and p, agreeing `g^xy mod p`. An elliptic-curve or montgomery pair agrees a
450
444
  * secret through the same call and would be emitted under the same OID, which names an operation
451
445
  * the recipient would not be performing. */
452
- if (eePriv.asymmetricKeyType !== "dh" || caPub.asymmetricKeyType !== "dh") {
446
+ if (guard.crypto.keyType(eePriv) !== "dh" || guard.crypto.keyType(caPub) !== "dh") {
453
447
  /** @internal A key this runtime imported but did not classify reports no asymmetricKeyType, which
454
448
  * is what an X9.42 dhpublicnumber SubjectPublicKeyInfo does here where the PKCS#3 dhKeyAgreement
455
449
  * form is classified. The agreement refuses such a key on its own, so naming the unrecognized
@@ -459,7 +453,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
459
453
  }
460
454
  /** @internal The agreement's own Buffer, not a copy of it: wrapping it would leave the original
461
455
  * holding the secret with nothing to clear it. */
462
- try { zz = _diffieHellman({ privateKey: eePriv, publicKey: caPub }); }
456
+ try { zz = guard.crypto.diffieHellman({ privateKey: eePriv, publicKey: caPub }); }
463
457
  catch (e) { throw _err("crmf/bad-popo", "the requester's key and the authority's key did not agree a secret; this proof needs a key on the authority's own parameters (RFC 4211 sec. 4.3)", e); }
464
458
  /** @internal K = SHA1(LeadingInfo | ZZ | TrailingInfo) (RFC 2875 sec. 3, step 3c), under the
465
459
  * digest the proof's own algorithm identifier names. */
@@ -762,7 +756,7 @@ function _x942ToPkcs3(spkiBytes, what) {
762
756
  /** @internal How a key reads in the refusal above. A key the runtime imported without classifying
763
757
  * carries no asymmetricKeyType, and reporting that as a type name says nothing an operator can act on. */
764
758
  function _keyTypeLabel(what, key) {
765
- var type = key && key.asymmetricKeyType;
759
+ var type = guard.crypto.keyTypeOf(key);
766
760
  if (typeof type !== "string" || type === "") {
767
761
  return what + " carries an algorithm this runtime does not recognize as a key it can agree with";
768
762
  }
package/lib/csr-sign.js CHANGED
@@ -26,6 +26,9 @@ var pkiBuild = require("./pki-build");
26
26
  var frameworkError = require("./framework-error");
27
27
  var guard = require("./guard-all");
28
28
  var intrinsic = require("./guard-intrinsic");
29
+ /** @internal The append every list here is built with: `push` stores at the index and a store
30
+ * consults a setter inherited there, and these lists become the bytes that get signed. */
31
+ var _push = intrinsic.append;
29
32
  /** @internal The promise a self-check is awaited through, built from the constructor captured at load.
30
33
  * `Promise.resolve` builds from its RECEIVER, so reading the global binding at the call hands the
31
34
  * construction to whatever that binding holds, and a constructor settling without awaiting its
@@ -224,7 +227,7 @@ function _sign(spec, key, opts) {
224
227
  function addAttr(attrType, valueTlv) {
225
228
  if (seenAttr[attrType]) throw _err("csr/bad-input", "duplicate " + (oid.name(attrType) || attrType) + " attribute");
226
229
  seenAttr[attrType] = true;
227
- attrs.push(b.sequence([b.oid(attrType), b.set([valueTlv])]));
230
+ _push(attrs,b.sequence([b.oid(attrType), b.set([valueTlv])]));
228
231
  }
229
232
  if (spec.extensionRequest != null) addAttr(O("extensionRequest"), _buildRequestedExtensions(spec.extensionRequest, subjectSpki));
230
233
  if (spec.challengePassword != null) addAttr(O("challengePassword"), _challengePassword(spec.challengePassword));
@@ -259,7 +262,7 @@ function _sign(spec, key, opts) {
259
262
  if (!n.children[1].children || n.children[1].children.length === 0) throw _err("csr/bad-input", "pre-encoded attribute [" + i + "] value SET must contain at least one value (RFC 2986 SET SIZE(1..MAX))");
260
263
  if (seenAttr[at]) throw _err("csr/bad-input", "duplicate " + (oid.name(at) || at) + " attribute");
261
264
  seenAttr[at] = true;
262
- attrs.push(b.raw(der));
265
+ _push(attrs,b.raw(der));
263
266
  });
264
267
  }
265
268
 
package/lib/ct.js CHANGED
@@ -39,7 +39,6 @@
39
39
  * bounded TLS-struct decode, fail-closed.
40
40
  */
41
41
 
42
- var nodeCrypto = require("crypto");
43
42
  var asn1 = require("./asn1-der.js");
44
43
  var constants = require("./constants.js");
45
44
  var frameworkError = require("./framework-error.js");
@@ -64,6 +63,7 @@ var _bufferCompare = intrinsic.compare;
64
63
  var _subarray = intrinsic.subarray;
65
64
  var _toLowerCase = intrinsic.toLowerCase;
66
65
  var _ctTrim = intrinsic.uncurry(String.prototype.trim);
66
+ var _writeBigUInt64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
67
67
  var _bufCopy = intrinsic.uncurry(Buffer.prototype.copy);
68
68
  var _writeU64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
69
69
  var _searchSet = intrinsic.uncurry(URLSearchParams.prototype.set);
@@ -293,8 +293,11 @@ function parseSctList(extValue) {
293
293
  }
294
294
  sctCount.tick();
295
295
  var one = _parseSct(outer.subReader(sctLen, "ct/list-trailing-bytes"), sctLen);
296
- if (one.unknown) { var u = { version: one.version, rawSct: one.rawSct }; unknownScts.push(u); all.push(u); }
297
- else { scts.push(one); all.push(one); }
296
+ /** @internal The parsed timestamps are appended by defining their indexes: the lists a caller
297
+ * reads its verdict from, and the `all` list a policy counts, are what a numeric setter on the
298
+ * array prototype would otherwise take an entry out of. */
299
+ if (one.unknown) { var u = { version: one.version, rawSct: one.rawSct }; intrinsic.append(unknownScts, u); intrinsic.append(all, u); }
300
+ else { intrinsic.append(scts, one); intrinsic.append(all, one); }
298
301
  }
299
302
  return guard.verdict.of({ scts: scts, unknownScts: unknownScts, all: all });
300
303
  }
@@ -366,29 +369,36 @@ function reconstructSignedData(entry, sct) {
366
369
  throw new CtError("ct/bad-input", "reconstructSignedData expects a decoded v1 SCT from parseSctList().scts[]");
367
370
  }
368
371
  var tsVal = guard.range.uint64(sct.timestamp, _ctErr, "ct/bad-input", "sct.timestamp (RFC 6962 3.2)");
372
+ /** @internal EVERY component of this preimage is appended by defining its index, and the
373
+ * concatenation is the captured one. These bytes are what a log's signature is verified over, so a
374
+ * numeric setter inherited from the array prototype replacing any one of them, the version, the
375
+ * signature type, the timestamp, the entry type, the certificate or the extensions, puts the
376
+ * verification on bytes the log never signed. Converting only the timestamp left the rest open,
377
+ * which is the whole class: the rule belongs to the function, not to the line it was found on. */
369
378
  var parts = [];
370
- parts.push(_bufferFrom([sct.version & 0xff]));
371
- parts.push(_bufferFrom([0]));
372
- var ts = _bufferAlloc(8); ts.writeBigUInt64BE(tsVal); parts.push(ts);
373
- parts.push(_bufferFrom([(entryType >> 8) & 0xff, entryType & 0xff]));
379
+ intrinsic.append(parts, _bufferFrom([sct.version & 0xff]));
380
+ intrinsic.append(parts, _bufferFrom([0]));
381
+ var ts = _bufferAlloc(8); _writeBigUInt64BE(ts, tsVal); intrinsic.append(parts, ts);
382
+ intrinsic.append(parts, _bufferFrom([(entryType >> 8) & 0xff, entryType & 0xff]));
374
383
  if (entryType === 0) {
375
384
  var cert = _toBuffer(entry.leafCert, "leafCert", undefined, undefined, 0xffffff, "ct/bad-tbs-length");
376
- parts.push(_u24Bytes(cert.length)); parts.push(cert);
385
+ intrinsic.append(parts, _u24Bytes(cert.length)); intrinsic.append(parts, cert);
377
386
  } else {
378
387
  var ikh = _toBuffer(entry.issuerKeyHash, "issuerKeyHash");
379
388
  if (ikh.length !== 32) {
380
389
  throw new CtError("ct/bad-issuer-key-hash", "issuer_key_hash must be exactly 32 bytes (SHA-256 of the issuer SPKI), got " + ikh.length + " (RFC 6962 sec. 3.2)");
381
390
  }
382
391
  var tbs = _toBuffer(entry.tbsCertificate, "tbsCertificate", undefined, undefined, 0xffffff, "ct/bad-tbs-length");
383
- parts.push(ikh);
384
- parts.push(_u24Bytes(tbs.length)); parts.push(tbs);
392
+ intrinsic.append(parts, ikh);
393
+ intrinsic.append(parts, _u24Bytes(tbs.length)); intrinsic.append(parts, tbs);
385
394
  }
386
395
  var ext = _toBuffer(sct.extensions, "sct.extensions", undefined, undefined, 0xffff, "ct/bad-extensions");
387
396
  if (ext.length > 0xffff) {
388
397
  throw new CtError("ct/bad-extensions", "CtExtensions must be 0..65535 bytes, got " + ext.length + " (RFC 6962 3.2)");
389
398
  }
390
- parts.push(_bufferFrom([(ext.length >> 8) & 0xff, ext.length & 0xff])); parts.push(ext);
391
- return Buffer.concat(parts);
399
+ intrinsic.append(parts, _bufferFrom([(ext.length >> 8) & 0xff, ext.length & 0xff]));
400
+ intrinsic.append(parts, ext);
401
+ return intrinsic.bufferConcat(parts);
392
402
  }
393
403
 
394
404
  var CT_HASH = intrinsic.assign(intrinsic.create(null), { sha256: "SHA-256" });
@@ -584,7 +594,7 @@ function encodeSctList(scts) {
584
594
  var el = ew.build();
585
595
  total += el.length;
586
596
  if (total > 0xffff) throw new CtError("ct/too-large", "the SCT list body exceeds the 65535-byte maximum (RFC 6962 sec. 3.3)");
587
- elements.push(el);
597
+ intrinsic.append(elements, el);
588
598
  }
589
599
  var lw = new TlsWriter();
590
600
  lw.vector(2, 1, 0xffff, Buffer.concat(elements, total), "ct/too-large");
@@ -594,11 +604,14 @@ function encodeSctList(scts) {
594
604
  function _logKeyMaterial(logKey) {
595
605
  try {
596
606
  var keyObj;
597
- if (logKey && typeof logKey === "object" && logKey.asymmetricKeyType) keyObj = logKey;
598
- else if (Buffer.isBuffer(logKey)) keyObj = nodeCrypto.createPrivateKey({ key: logKey, format: "der", type: "pkcs8" });
599
- else keyObj = nodeCrypto.createPrivateKey(logKey);
600
- if (keyObj.type !== "private") throw new CtError("ct/bad-input", "signSct requires the CT log PRIVATE key");
601
- return { pkcs8: keyObj.export({ type: "pkcs8", format: "der" }), spki: nodeCrypto.createPublicKey(keyObj).export({ type: "spki", format: "der" }) };
607
+ if (guard.crypto.keyTypeOf(logKey)) keyObj = logKey;
608
+ else if (Buffer.isBuffer(logKey)) keyObj = guard.crypto.privateKey({ key: logKey, format: "der", type: "pkcs8" });
609
+ else keyObj = guard.crypto.privateKey(logKey);
610
+ if (guard.crypto.keyKind(keyObj) !== "private") throw new CtError("ct/bad-input", "signSct requires the CT log PRIVATE key");
611
+ return {
612
+ pkcs8: guard.crypto.exportKey(keyObj, { type: "pkcs8", format: "der" }),
613
+ spki: guard.crypto.exportKey(guard.crypto.publicKey(keyObj), { type: "spki", format: "der" }),
614
+ };
602
615
  } catch (e) {
603
616
  if (e instanceof CtError) throw e;
604
617
  throw new CtError("ct/bad-input", "the CT log private key could not be loaded", e);
@@ -714,7 +727,7 @@ function _parseLog(log, operatorName) {
714
727
  var statedId = guard.encoding.base64(log.log_id, 64, _ctErr, "ct/bad-log-list", "the CT log id");
715
728
  if (statedId.length !== 32) throw _ctErr("ct/bad-log-list", "a CT log_id must be 32 bytes (SHA-256), got " + statedId.length);
716
729
  _spkiAlg(spki);
717
- var logId = nodeCrypto.createHash("sha256").update(spki).digest();
730
+ var logId = guard.crypto.digest("sha256", spki);
718
731
  if (!logId.equals(statedId)) throw _ctErr("ct/log-id-mismatch", "the CT log_id does not match SHA-256 of the log key (RFC 6962 sec. 3.2)");
719
732
  return guard.verdict.of({
720
733
  logId: logId, logIdHex: logId.toString("hex"), key: spki,
@@ -803,7 +816,7 @@ function parseLogList(json, opts) {
803
816
  continue;
804
817
  }
805
818
  byLogId[rec.logIdHex] = rec;
806
- logs.push(rec);
819
+ intrinsic.append(logs, rec);
807
820
  }
808
821
  }
809
822
  }
@@ -1092,15 +1105,15 @@ function x509CertEntry(cert, issuer) {
1092
1105
  for (var j = 0; j < extsSeq.children.length; j++) {
1093
1106
  var ext = extsSeq.children[j];
1094
1107
  if (ext.children[0] && intrinsic.bufferEquals(ext.children[0].bytes, sctOid)) { removed++; continue; }
1095
- intrinsic.push(kept, ext.bytes);
1108
+ intrinsic.append(kept, ext.bytes);
1096
1109
  }
1097
1110
  if (removed === 0) throw _ctErr("ct/no-sct-extension", "the certificate carries no signedCertificateTimestampList extension (RFC 6962 sec. 3.2)");
1098
1111
  var tbsChildren = [];
1099
1112
  for (var k = 0; k < tbs.children.length; k++) {
1100
- if (k !== wrapIdx) { intrinsic.push(tbsChildren, tbs.children[k].bytes); continue; }
1101
- if (kept.length > 0) intrinsic.push(tbsChildren, asn1.build.explicit(3, asn1.build.sequence(kept)));
1113
+ if (k !== wrapIdx) { intrinsic.append(tbsChildren, tbs.children[k].bytes); continue; }
1114
+ if (kept.length > 0) intrinsic.append(tbsChildren, asn1.build.explicit(3, asn1.build.sequence(kept)));
1102
1115
  }
1103
- var issuerKeyHash = nodeCrypto.createHash("sha256").update(issSpki).digest();
1116
+ var issuerKeyHash = guard.crypto.digest("sha256", issSpki);
1104
1117
  return { entryType: 1, tbsCertificate: asn1.build.sequence(tbsChildren), issuerKeyHash: issuerKeyHash };
1105
1118
  }
1106
1119
 
@@ -2017,7 +2030,7 @@ async function _addChain(opts, message, entryType) {
2017
2030
  ? _bufferAlloc(0) : _b64Field(doc, "extensions", "ct/bad-sct", "sct"),
2018
2031
  signature: _b64Field(doc, "signature", "ct/bad-sct", "sct"),
2019
2032
  };
2020
- var pinnedId = nodeCrypto.createHash("sha256").update(pinnedKey).digest();
2033
+ var pinnedId = guard.crypto.digest("sha256", pinnedKey);
2021
2034
  if (_bufferCompare(sct.logId, pinnedId) !== 0) {
2022
2035
  throw _ctErr("ct/sct-untrusted", "the SCT names log id " + _bufToString(sct.logId, "hex") +
2023
2036
  " where the pinned key's id is " + _bufToString(pinnedId, "hex") + " -- it is not this log's receipt");