@blamejs/pki 0.8.55 → 0.8.57

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 (56) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +1 -1
  3. package/lib/acme.js +2 -2
  4. package/lib/asn1-der.js +17 -5
  5. package/lib/attrcert-verify.js +1 -1
  6. package/lib/cmc-verify.js +1 -1
  7. package/lib/cmp-session.js +2 -2
  8. package/lib/cmp-verify.js +2 -2
  9. package/lib/cms-decrypt.js +4 -1
  10. package/lib/cms-encrypt.js +4 -1
  11. package/lib/cms-sign.js +26 -12
  12. package/lib/cms-verify.js +1 -1
  13. package/lib/composite-kem.js +30 -12
  14. package/lib/composite-sig.js +42 -23
  15. package/lib/constants.js +7 -2
  16. package/lib/crl-verify.js +1 -1
  17. package/lib/crmf-sign.js +72 -43
  18. package/lib/crmf-verify.js +1 -1
  19. package/lib/csr-verify.js +1 -1
  20. package/lib/ct.js +2 -2
  21. package/lib/edwards-point.js +1 -1
  22. package/lib/est.js +3 -3
  23. package/lib/guard-async.js +22 -1
  24. package/lib/guard-bytes.js +6 -3
  25. package/lib/guard-identifier.js +1 -1
  26. package/lib/guard-intrinsic.js +474 -0
  27. package/lib/guard-parsed.js +23 -7
  28. package/lib/http-digest.js +146 -62
  29. package/lib/http-transport.js +82 -17
  30. package/lib/identity-match.js +2 -2
  31. package/lib/inspect.js +1 -1
  32. package/lib/lint.js +51 -3
  33. package/lib/merkle.js +2 -2
  34. package/lib/ocsp-request-verify.js +1 -1
  35. package/lib/ocsp.js +53 -22
  36. package/lib/oid.js +7 -0
  37. package/lib/path-validate.js +169 -76
  38. package/lib/pbes2.js +14 -7
  39. package/lib/schema-attrcert.js +2 -2
  40. package/lib/schema-cmc.js +2 -2
  41. package/lib/schema-cmp.js +2 -2
  42. package/lib/schema-cms.js +115 -10
  43. package/lib/schema-crmf.js +2 -2
  44. package/lib/schema-csr.js +2 -2
  45. package/lib/schema-ocsp.js +41 -6
  46. package/lib/schema-pkix.js +3 -3
  47. package/lib/schema-x509.js +2 -2
  48. package/lib/sigstore.js +1 -1
  49. package/lib/tlog.js +7 -4
  50. package/lib/trust.js +187 -104
  51. package/lib/tsp-sign.js +1 -1
  52. package/lib/webauthn-mds.js +257 -121
  53. package/lib/webauthn.js +327 -164
  54. package/lib/webcrypto.js +10 -3
  55. package/package.json +1 -1
  56. package/sbom.cdx.json +6 -6
@@ -24,7 +24,6 @@ var _promiseResolve = _intrinsic.uncurry(_intrinsic.promiseResolve);
24
24
  /** @internal The aggregator is the same defect one step out: the composite verdict is `ok` only when
25
25
  * BOTH component verifications resolve true, so a replaced `all` that resolves `[true, true]` without
26
26
  * awaiting either half reports a forged signature as verified. */
27
- var _promiseAll = _intrinsic.uncurry(_intrinsic.promiseAll);
28
27
  var _b = asn1.build;
29
28
 
30
29
  function _codeOf(e, fallback) {
@@ -85,7 +84,11 @@ function compositeMprime(d, phBuf, ctx) {
85
84
  function _verifyTradComponent(trad, tradPK, tradSig, mprime, E, badSig) {
86
85
  if (trad.ec) {
87
86
  if (tradPK.length < 1 || tradPK[0] !== 0x04) return _promiseResolve(_Promise, false);
88
- return subtle.importKey("spki", _ecSpki(trad.ec, tradPK), { name: "ECDSA" }, false, ["verify"]).then(function (k) {
87
+ /** @internal Every continuation on this path comes from the capture. A continuation is read off
88
+ * the promise at the call, and these deliver the two component verdicts a composite signature is
89
+ * the conjunction of: a replacement settling either one reports a component as verified without
90
+ * it having been checked, and the path validator that calls this reads the conjunction. */
91
+ return _intrinsic.chain(subtle.importKey("spki", _ecSpki(trad.ec, tradPK), { name: "ECDSA" }, false, ["verify"]), function (k) {
89
92
  var p1363 = validator.sig.ecdsaDerToP1363(tradSig, trad.ec, E, badSig);
90
93
  return _subtleVerify(subtle, { name: "ECDSA", hash: trad.hash }, k, p1363, mprime);
91
94
  });
@@ -94,8 +97,8 @@ function _verifyTradComponent(trad, tradPK, tradSig, mprime, E, badSig) {
94
97
  if (!edwardsPoint.validate(tradPK, trad.eddsa === "Ed25519" ? 6 : 7)) {
95
98
  throw new E(badSig, "the composite EdDSA component public key is not a valid, full-order Edwards point");
96
99
  }
97
- return subtle.importKey("spki", _edSpki(trad.eddsa, tradPK), { name: trad.eddsa }, false, ["verify"])
98
- .then(function (k) { return _subtleVerify(subtle, { name: trad.eddsa }, k, tradSig, mprime); });
100
+ return _intrinsic.chain(subtle.importKey("spki", _edSpki(trad.eddsa, tradPK), { name: trad.eddsa }, false, ["verify"]),
101
+ function (k) { return _subtleVerify(subtle, { name: trad.eddsa }, k, tradSig, mprime); });
99
102
  }
100
103
  if (trad.rsaPss || trad.rsaPkcs1) {
101
104
  var bits;
@@ -103,11 +106,11 @@ function _verifyTradComponent(trad, tradPK, tradSig, mprime, E, badSig) {
103
106
  catch (_e) { return _promiseResolve(_Promise, false); }
104
107
  if (bits !== trad.rsaBits) return _promiseResolve(_Promise, false);
105
108
  if (trad.rsaPss) {
106
- return subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSA-PSS", hash: trad.hash }, false, ["verify"])
107
- .then(function (k) { return _subtleVerify(subtle, { name: "RSA-PSS", saltLength: trad.salt }, k, tradSig, mprime); });
109
+ return _intrinsic.chain(subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSA-PSS", hash: trad.hash }, false, ["verify"]),
110
+ function (k) { return _subtleVerify(subtle, { name: "RSA-PSS", saltLength: trad.salt }, k, tradSig, mprime); });
108
111
  }
109
- return subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSASSA-PKCS1-v1_5", hash: trad.hash }, false, ["verify"])
110
- .then(function (k) { return _subtleVerify(subtle, { name: "RSASSA-PKCS1-v1_5" }, k, tradSig, mprime); });
112
+ return _intrinsic.chain(subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSASSA-PKCS1-v1_5", hash: trad.hash }, false, ["verify"]),
113
+ function (k) { return _subtleVerify(subtle, { name: "RSASSA-PKCS1-v1_5" }, k, tradSig, mprime); });
111
114
  }
112
115
  return _promiseResolve(_Promise, false);
113
116
  }
@@ -132,13 +135,21 @@ function compositeVerify(spkiBytes, sigBytes, message, d, E, unsupported, badSig
132
135
  }
133
136
  var mldsaPK = rawKey.subarray(0, d.mldsaPk), tradPK = rawKey.subarray(d.mldsaPk);
134
137
  var mldsaSig = sigBytes.subarray(0, d.mldsaSig), tradSig = sigBytes.subarray(d.mldsaSig);
135
- return subtle.digest({ name: d.ph }, message).then(function (phBuf) {
138
+ var combined = _intrinsic.chain(subtle.digest({ name: d.ph }, message), function (phBuf) {
136
139
  var mprime = compositeMprime(d, phBuf);
137
- var mldsaP = subtle.importKey("spki", _mldsaSpki(d.mldsaOid, mldsaPK), { name: d.mldsa }, false, ["verify"])
138
- .then(function (mk) { return _subtleVerify(subtle, { name: d.mldsa, context: d.label }, mk, mldsaSig, mprime); });
140
+ var mldsaP = _intrinsic.chain(subtle.importKey("spki", _mldsaSpki(d.mldsaOid, mldsaPK), { name: d.mldsa }, false, ["verify"]),
141
+ function (mk) { return _subtleVerify(subtle, { name: d.mldsa, context: d.label }, mk, mldsaSig, mprime); });
139
142
  var tradP = _verifyTradComponent(d.trad, tradPK, tradSig, mprime, E, badSig);
140
- return _promiseAll(_Promise, [mldsaP, tradP]).then(function (r) { return _verdictOf({ ok: r[0] === true && r[1] === true }); });
141
- }).catch(function (e) { return _verdictOf({ ok: false, code: _codeOf(e, badSig), error: e }); });
143
+ /** @internal The conjunction is read from an aggregate that consults nothing replaceable: both
144
+ * components must answer `true`, so a settled value in place of either is a composite signature
145
+ * reported as verified on one half or on neither. A captured `Promise.all` is not enough, since
146
+ * it reads `resolve` off the constructor at each call and a replacement there answers for every
147
+ * member without any component being awaited. */
148
+ return _intrinsic.chain(_intrinsic.allOf([mldsaP, tradP]),
149
+ function (r) { return _verdictOf({ ok: r[0] === true && r[1] === true }); });
150
+ });
151
+ return _intrinsic.chain(combined, undefined,
152
+ function (e) { return _verdictOf({ ok: false, code: _codeOf(e, badSig), error: e }); });
142
153
  }
143
154
 
144
155
  function resolveCompositeDescriptor(sigAlg, E, unsupported) {
@@ -151,27 +162,35 @@ function resolveCompositeDescriptor(sigAlg, E, unsupported) {
151
162
  }
152
163
 
153
164
  function compositeSign(d, keys, message, ctx) {
154
- return subtle.digest({ name: d.ph }, message).then(function (phBuf) {
165
+ /** @internal The signing half is continued through the captures too. Its output is the signature a
166
+ * verifier is then held to, so a replacement settling a component hands back bytes neither key
167
+ * produced and the signature does not verify anywhere. */
168
+ return _intrinsic.chain(subtle.digest({ name: d.ph }, message), function (phBuf) {
155
169
  var mprime = compositeMprime(d, phBuf, ctx);
156
- var mldsaP = subtle.importKey("pkcs8", keys.mldsa, { name: d.mldsa }, false, ["sign"])
157
- .then(function (k) { return subtle.sign({ name: d.mldsa, context: d.label }, k, mprime); });
170
+ var mldsaP = _intrinsic.chain(subtle.importKey("pkcs8", keys.mldsa, { name: d.mldsa }, false, ["sign"]),
171
+ function (k) { return subtle.sign({ name: d.mldsa, context: d.label }, k, mprime); });
158
172
  var tradP = _signTradComponent(d.trad, keys.trad, mprime);
159
- return _promiseAll(_Promise, [mldsaP, tradP]).then(function (s) { return Buffer.concat([Buffer.from(s[0]), Buffer.from(s[1])]); });
173
+ return _intrinsic.chain(_intrinsic.allOf([mldsaP, tradP]),
174
+ function (s) { return Buffer.concat([Buffer.from(s[0]), Buffer.from(s[1])]); });
160
175
  });
161
176
  }
162
177
  function _signTradComponent(trad, pkcs8, mprime) {
163
178
  if (trad.ec) {
164
- return subtle.importKey("pkcs8", pkcs8, { name: "ECDSA", namedCurve: trad.ec }, false, ["sign"])
165
- .then(function (k) { return subtle.sign({ name: "ECDSA", hash: trad.hash }, k, mprime); })
166
- .then(function (raw) { var r = Buffer.from(raw); return validator.sig.rawToEcdsaDer(r, r.length / 2); });
179
+ var ecSigned = _intrinsic.chain(subtle.importKey("pkcs8", pkcs8, { name: "ECDSA", namedCurve: trad.ec }, false, ["sign"]),
180
+ function (k) { return subtle.sign({ name: "ECDSA", hash: trad.hash }, k, mprime); });
181
+ return _intrinsic.chain(ecSigned,
182
+ function (raw) { var r = Buffer.from(raw); return validator.sig.rawToEcdsaDer(r, r.length / 2); });
167
183
  }
168
184
  if (trad.eddsa) {
169
- return subtle.importKey("pkcs8", pkcs8, { name: trad.eddsa }, false, ["sign"])
170
- .then(function (k) { return subtle.sign({ name: trad.eddsa }, k, mprime); }).then(function (s) { return Buffer.from(s); });
185
+ var edSigned = _intrinsic.chain(subtle.importKey("pkcs8", pkcs8, { name: trad.eddsa }, false, ["sign"]),
186
+ function (k) { return subtle.sign({ name: trad.eddsa }, k, mprime); });
187
+ return _intrinsic.chain(edSigned, function (s) { return Buffer.from(s); });
171
188
  }
172
189
  var imp = trad.rsaPss ? { name: "RSA-PSS", hash: trad.hash } : { name: "RSASSA-PKCS1-v1_5", hash: trad.hash };
173
190
  var alg = trad.rsaPss ? { name: "RSA-PSS", saltLength: trad.salt } : { name: "RSASSA-PKCS1-v1_5" };
174
- return subtle.importKey("pkcs8", pkcs8, imp, false, ["sign"]).then(function (k) { return subtle.sign(alg, k, mprime); }).then(function (s) { return Buffer.from(s); });
191
+ var rsaSigned = _intrinsic.chain(subtle.importKey("pkcs8", pkcs8, imp, false, ["sign"]),
192
+ function (k) { return subtle.sign(alg, k, mprime); });
193
+ return _intrinsic.chain(rsaSigned, function (s) { return Buffer.from(s); });
175
194
  }
176
195
 
177
196
  module.exports = {
package/lib/constants.js CHANGED
@@ -319,10 +319,15 @@ Object.freeze(NAMES);
319
319
 
320
320
  var VERSION = require("../package.json").version;
321
321
 
322
- module.exports = {
322
+ /** @internal Frozen, because these tables are read BY NAME at call time to decide an admission.
323
+ * `cms.sign` asks `NAMES.WEAK_DIGESTS` whether a digest is weak and `NAMES.TIMESTAMP_IMPRINT_DIGESTS`
324
+ * whether one is permitted at all, so a caller able to assign `constants.NAMES` a copy with an empty
325
+ * weak list turns the refusal off and a SHA-1 timestamp imprint is accepted. Freezing the tables
326
+ * alone left the PROPERTIES naming them writable, which is the same hole one level out. */
327
+ module.exports = Object.freeze({
323
328
  TIME: TIME,
324
329
  BYTES: BYTES,
325
330
  LIMITS: LIMITS,
326
331
  NAMES: NAMES,
327
332
  version: VERSION,
328
- };
333
+ });
package/lib/crl-verify.js CHANGED
@@ -12,4 +12,4 @@ function verifyCrlSignature(crl, spkiBytes) {
12
12
  return _seam.verify(crl.signatureAlgorithm, crl.signatureValue, spkiBytes, crl.tbsBytes);
13
13
  }
14
14
 
15
- module.exports = { setEngine: _seam.setEngine, verifyCrlSignature: verifyCrlSignature };
15
+ module.exports = Object.freeze({ setEngine: _seam.setEngine, verifyCrlSignature: verifyCrlSignature });
package/lib/crmf-sign.js CHANGED
@@ -43,10 +43,9 @@ var _Promise = intrinsic.Promise;
43
43
  var _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
44
44
  /** @internal `verifyPop`'s verdict is the aggregate of the per-message results, so a replaced `all`
45
45
  * that resolves a fabricated array reports an unverified proof of possession as verified. */
46
- var _promiseAll = intrinsic.uncurry(intrinsic.promiseAll);
47
46
  var _hasOwn = intrinsic.hasOwn;
48
47
  var _isBuffer = intrinsic.isBuffer;
49
- var _push = intrinsic.push, _String = intrinsic.String;
48
+ var _String = intrinsic.String;
50
49
  var _stringify = intrinsic.stringify;
51
50
  var cms = require("./schema-cms");
52
51
  var possession = require("./possession");
@@ -108,7 +107,7 @@ function _ctlPossession(v) {
108
107
  b.raw(_b.reqDer(issuerRaw, "statementOfPossession signer.issuer (the signature certificate's issuer Name DER)")),
109
108
  b.integer(guard.range.authoredInteger(signer.serialNumber, _err, "crmf/bad-controls", "statementOfPossession signer.serialNumber")),
110
109
  ])];
111
- if (v.certificate != null) _push(fields, b.raw(_b.reqDer(v.certificate, "statementOfPossession certificate")));
110
+ if (v.certificate != null) guard.list.append(fields, b.raw(_b.reqDer(v.certificate, "statementOfPossession certificate")));
112
111
  var der = b.sequence(fields);
113
112
  try { possession.parse(der); }
114
113
  catch (e) { throw _err("crmf/bad-controls", "statementOfPossession: " + ((e && e.message) || _String(e)), e); }
@@ -177,8 +176,8 @@ function _encodeOptionalValidity(validity) {
177
176
  var nb = validity.notBefore, na = validity.notAfter;
178
177
  if (nb == null && na == null) throw _err("crmf/bad-validity", "validity must contain notBefore or notAfter (RFC 4211 sec. 5)");
179
178
  var parts = [];
180
- if (nb != null) parts.push(b.explicit(0, _b.timeDer(nb, "validity notBefore")));
181
- if (na != null) parts.push(b.explicit(1, _b.timeDer(na, "validity notAfter")));
179
+ if (nb != null) guard.list.append(parts, b.explicit(0, _b.timeDer(nb, "validity notBefore")));
180
+ if (na != null) guard.list.append(parts, b.explicit(1, _b.timeDer(na, "validity notAfter")));
182
181
  // allow:nan-date-comparison-unguarded -- both instants passed timeDer's guard.time.assertEncodable above.
183
182
  if (nb != null && na != null && guard.time.instantOf(nb) > guard.time.instantOf(na)) throw _err("crmf/bad-validity", "notBefore must not be after notAfter");
184
183
  return b.implicit(4, b.sequence(parts));
@@ -190,19 +189,22 @@ function _encodeCertTemplate(tpl, opts) {
190
189
  var fields = [];
191
190
  if (tpl.version != null) {
192
191
  if (tpl.version !== 2) throw _err("crmf/bad-version", "certTemplate version MUST be 2 (v3) if supplied (RFC 4211 sec. 5)");
193
- fields.push(b.implicit(0, b.integer(2n)));
192
+ guard.list.append(fields, b.implicit(0, b.integer(2n)));
194
193
  }
195
- if (tpl.serialNumber != null) fields.push(b.implicit(1, _b.serialInteger(tpl.serialNumber)));
196
- if (tpl.issuer != null) fields.push(b.explicit(3, _b.encodeName(tpl.issuer)));
197
- if (tpl.validity != null) fields.push(_encodeOptionalValidity(tpl.validity));
198
- if (tpl.subject != null) fields.push(b.explicit(5, _b.encodeName(tpl.subject)));
194
+ /** @internal Appended through the guard. These members are the template a proof of possession is
195
+ * computed over and a CA issues from, so a replaced append that drops or substitutes one changes
196
+ * what was requested from what was proven. */
197
+ if (tpl.serialNumber != null) guard.list.append(fields, b.implicit(1, _b.serialInteger(tpl.serialNumber)));
198
+ if (tpl.issuer != null) guard.list.append(fields, b.explicit(3, _b.encodeName(tpl.issuer)));
199
+ if (tpl.validity != null) guard.list.append(fields, _encodeOptionalValidity(tpl.validity));
200
+ if (tpl.subject != null) guard.list.append(fields, b.explicit(5, _b.encodeName(tpl.subject)));
199
201
  var spki = null;
200
202
  if (tpl.publicKey != null) {
201
203
  spki = _b.reqDer(tpl.publicKey, "certTemplate.publicKey (the SPKI DER of the requested key)");
202
204
  _b.assertValidSpki(spki, "certTemplate.publicKey");
203
- fields.push(b.implicit(6, spki));
205
+ guard.list.append(fields, b.implicit(6, spki));
204
206
  }
205
- if (tpl.extensions != null) fields.push(b.implicit(9, _b.requestedExtensions(tpl.extensions, spki)));
207
+ if (tpl.extensions != null) guard.list.append(fields, b.implicit(9, _b.requestedExtensions(tpl.extensions, spki)));
206
208
  return { der: b.sequence(fields), spki: spki, complete: tpl.subject != null && tpl.publicKey != null };
207
209
  }
208
210
 
@@ -237,7 +239,7 @@ function _buildAttrTypeAndValues(spec, code, label, valueMap, collect) {
237
239
  var typeOid = O(k);
238
240
  if (seen[typeOid]) throw _err(code, "duplicate " + label + " type " + k);
239
241
  seen[typeOid] = true;
240
- out.push(b.sequence([b.oid(typeOid), enc(spec[k])]));
242
+ guard.list.append(out, b.sequence([b.oid(typeOid), enc(spec[k])]));
241
243
  });
242
244
  if (!out.length) throw _err(code, label + " must carry at least one entry");
243
245
  return b.sequence(out);
@@ -916,19 +918,23 @@ function _buildEncryptedKeyPop(pop, outerTag, template) {
916
918
  "the proof is that the enclosed private key is the one being certified (RFC 4211 sec. 4.2)");
917
919
  }
918
920
  encKeyWithIdDer = _encKeyWithID(privateKeyDer, pop.identifier);
919
- return _assertEnclosedKeyMatches(privateKeyDer, template.spki).then(function () {
920
- return cmsEncrypt.encrypt(encKeyWithIdDer, recipients, { contentType: "encKeyWithID", contentEncryptionAlgorithm: cea })
921
- .then(null, function (e) {
922
- if (e instanceof CrmfError) throw e;
923
- throw _err("crmf/bad-input", "the encryptedKey proof of possession could not envelope the private key to " +
924
- "pop.recipients: " + ((e && e.message) || e), e);
925
- });
926
- })
927
- .then(function (contentInfo) {
928
- var inner = _bareEnvelopedData(contentInfo);
929
- return b.explicit(outerTag, b.implicit(4, inner));
930
- })
931
- .then(function (out) { wipe(); return out; }, function (e) { wipe(); throw e; });
921
+ /** @internal Each step is continued through the capture. The first decides whether the enclosed
922
+ * private key IS the one being certified, which is the whole proof, and the last is what wipes the
923
+ * key material whichever way the chain settles. */
924
+ var enveloped = intrinsic.chain(_assertEnclosedKeyMatches(privateKeyDer, template.spki), function () {
925
+ var encrypted = cmsEncrypt.encrypt(encKeyWithIdDer, recipients,
926
+ { contentType: "encKeyWithID", contentEncryptionAlgorithm: cea });
927
+ return intrinsic.chain(encrypted, null, function (e) {
928
+ if (e instanceof CrmfError) throw e;
929
+ throw _err("crmf/bad-input", "the encryptedKey proof of possession could not envelope the private key to " +
930
+ "pop.recipients: " + ((e && e.message) || e), e);
931
+ });
932
+ });
933
+ var wrapped = intrinsic.chain(enveloped, function (contentInfo) {
934
+ var inner = _bareEnvelopedData(contentInfo);
935
+ return b.explicit(outerTag, b.implicit(4, inner));
936
+ });
937
+ return intrinsic.chain(wrapped, function (out) { wipe(); return out; }, function (e) { wipe(); throw e; });
932
938
  }
933
939
  }
934
940
 
@@ -964,9 +970,9 @@ function _assertEnclosedKeyMatches(privateKeyDer, templateSpki) {
964
970
  * cannot use it, so those are proven by USING the key against the template. */
965
971
  var enclosedAlg = key.algorithmOidAt(privateKeyDer, 1);
966
972
  if (enclosedAlg !== null && !key.isDhOid(enclosedAlg)) return _assertEnclosedKeyCorresponds(privateKeyDer, templateSpki);
967
- return _promiseResolve(_Promise, undefined)
968
- .then(function () { return key.publicFromPrivate(privateKeyDer); })
969
- .then(function (derivedSpki) {
973
+ var derivedP = intrinsic.chain(_promiseResolve(_Promise, undefined),
974
+ function () { return key.publicFromPrivate(privateKeyDer); });
975
+ return intrinsic.chain(derivedP, function (derivedSpki) {
970
976
  var derived = guard.bytes.view(derivedSpki, CrmfError, "crmf/bad-input", "the derived public key");
971
977
  var wanted = guard.bytes.view(templateSpki, CrmfError, "crmf/bad-input", "certTemplate.publicKey");
972
978
  /** @internal A finite-field key names itself in either encoding here too, and an enclosed key
@@ -1074,12 +1080,20 @@ function _buildProofOfPossession(pop, certReqDer, template, signingKey, opts, po
1074
1080
  signedRegion = poposkSeq;
1075
1081
  poposkInputField = b.implicit(0, poposkSeq);
1076
1082
  }
1077
- return signScheme.signOverTbs(scheme, signingKey, signedRegion, _signE).then(function (sig) {
1078
- return _promiseResolve(_Promise, _b.assertSignatureVerifies(signedRegion, sig, provingSpki, scheme)).then(function () {
1083
+ /** @internal Both continuations are captured. The inner one runs after the proof's own signature
1084
+ * has been verified against the key being certified, so a replacement settling it emits a proof
1085
+ * whose signature was never checked against that key. */
1086
+ return intrinsic.chain(signScheme.signOverTbs(scheme, signingKey, signedRegion, _signE), function (sig) {
1087
+ var selfChecked = _promiseResolve(_Promise, _b.assertSignatureVerifies(signedRegion, sig, provingSpki, scheme));
1088
+ return intrinsic.chain(selfChecked, function () {
1079
1089
  var popoChildren = [];
1080
- if (poposkInputField) popoChildren.push(poposkInputField);
1081
- popoChildren.push(scheme.sigAlgId);
1082
- popoChildren.push(b.bitString(sig, 0));
1090
+ /** @internal Appended through the guard, which defines the index rather than calling a method
1091
+ * the prototype answers for. These three members ARE the proof: the signature value is added
1092
+ * AFTER it has been verified against the key being certified, so a replaced append that alters
1093
+ * it emits a proof whose bytes nothing checked. */
1094
+ if (poposkInputField) guard.list.append(popoChildren, poposkInputField);
1095
+ guard.list.append(popoChildren, scheme.sigAlgId);
1096
+ guard.list.append(popoChildren, b.bitString(sig, 0));
1083
1097
  return b.implicit(1, b.sequence(popoChildren));
1084
1098
  });
1085
1099
  }, function (e) {
@@ -1171,7 +1185,7 @@ function _buildCertReqMsg(spec, key, opts) {
1171
1185
  var template = _encodeCertTemplate(spec.certTemplate);
1172
1186
  var certReqChildren = [b.integer(_certReqId(spec.certReqId)), template.der];
1173
1187
  var encodedControls = [];
1174
- if (spec.controls != null) certReqChildren.push(_buildAttrTypeAndValues(spec.controls, "crmf/bad-controls", "controls", CONTROL_VALUE, encodedControls));
1188
+ if (spec.controls != null) guard.list.append(certReqChildren, _buildAttrTypeAndValues(spec.controls, "crmf/bad-controls", "controls", CONTROL_VALUE, encodedControls));
1175
1189
  var certReqDer = b.sequence(certReqChildren);
1176
1190
 
1177
1191
  /** @internal The key the RFC 9883 control names, when the request carries one: that key makes the
@@ -1196,10 +1210,12 @@ function _buildCertReqMsg(spec, key, opts) {
1196
1210
  possessionSpki = _encodedPossessionSpki(encodedControls);
1197
1211
  }
1198
1212
 
1199
- return _promiseResolve(_Promise, _buildProofOfPossession(spec.pop, certReqDer, template, signingKey, opts, possessionSpki)).then(function (popoDer) {
1213
+ var popoP = _promiseResolve(_Promise,
1214
+ _buildProofOfPossession(spec.pop, certReqDer, template, signingKey, opts, possessionSpki));
1215
+ return intrinsic.chain(popoP, function (popoDer) {
1200
1216
  var msgChildren = [certReqDer];
1201
- if (popoDer) msgChildren.push(popoDer);
1202
- if (spec.regInfo != null) msgChildren.push(_buildAttrTypeAndValues(spec.regInfo, "crmf/bad-reg-info", "regInfo", REGINFO_VALUE));
1217
+ if (popoDer) guard.list.append(msgChildren, popoDer);
1218
+ if (spec.regInfo != null) guard.list.append(msgChildren, _buildAttrTypeAndValues(spec.regInfo, "crmf/bad-reg-info", "regInfo", REGINFO_VALUE));
1203
1219
  return b.sequence(msgChildren);
1204
1220
  });
1205
1221
  }
@@ -1218,7 +1234,9 @@ function _build(spec, key, opts) {
1218
1234
  specs = [spec];
1219
1235
  }
1220
1236
  if (!specs.length) throw _err("crmf/bad-input", "at least one certificate request message is required (RFC 4211 sec. 3)");
1221
- return _promiseAll(_Promise, specs.map(function (s) { return _buildCertReqMsg(s, key, opts); })).then(function (msgs) {
1237
+ return intrinsic.chain(intrinsic.allOf(intrinsic.mapList(specs, function (s) {
1238
+ return _buildCertReqMsg(s, key, opts);
1239
+ })), function (msgs) {
1222
1240
  var der = b.sequence(msgs);
1223
1241
  if (opts.pem != null) {
1224
1242
  if (typeof opts.pem !== "string" || !opts.pem) throw _err("crmf/bad-input", "opts.pem must be a non-empty PEM label string");
@@ -1310,7 +1328,10 @@ function _verifyOne(msg) {
1310
1328
  spki = sopSpki;
1311
1329
  bound = false;
1312
1330
  }
1313
- return crmfVerify.verifyPopSignature(popo, spki, preimage).then(function (ok) {
1331
+ /** @internal The continuation comes from the capture. It is where the signature answer becomes this
1332
+ * message's verdict, so a replacement settling it hands back a record stating `verified: true` for
1333
+ * a proof nothing checked, and the aggregate above then reports the whole set as verified. */
1334
+ return intrinsic.chain(crmfVerify.verifyPopSignature(popo, spki, preimage), function (ok) {
1314
1335
  return guard.verdict.of(base, {
1315
1336
  valid: ok === true, verified: ok === true, method: "signature", cryptographicallyVerified: ok === true,
1316
1337
  subject: bound ? base.subject : null,
@@ -1368,9 +1389,17 @@ function _verifyOne(msg) {
1368
1389
  function verifyPop(messages) { return guard.async.deferred(function () { return _verifyPop(messages); }); }
1369
1390
  function _verifyPop(messages) {
1370
1391
  var parsed = _coerceMessages(messages);
1371
- return _promiseAll(_Promise, parsed.messages.map(_verifyOne)).then(function (out) {
1372
- var allVerified = out.length > 0 && out.every(function (m) { return m.verified === true; });
1373
- return guard.verdict.of({ valid: allVerified, verified: allVerified, messages: out });
1392
+ /** @internal The aggregate, the projection into it and the universal test over its results all come
1393
+ * from the captures. This IS the proof-of-possession verdict for a set of requests: the aggregate's
1394
+ * static form reads `resolve` off the constructor at each call, so a replacement answers for every
1395
+ * message without one being verified, and the test below is what requires all of them to have
1396
+ * verified. */
1397
+ return intrinsic.chain(intrinsic.allOf(intrinsic.mapList(parsed.messages, _verifyOne)), function (out) {
1398
+ var allVerified = out.length > 0 && intrinsic.everyOwn(out, function (m) { return m && m.verified === true; });
1399
+ /** @internal Copied before it is handed back. The aggregate's own list carries no prototype, so
1400
+ * that a `then` installed on `Array.prototype` cannot settle the aggregate with something else;
1401
+ * a caller reading `result.messages` expects an ordinary array it can iterate and map. */
1402
+ return guard.verdict.of({ valid: allVerified, verified: allVerified, messages: intrinsic.copyList(out) });
1374
1403
  });
1375
1404
  }
1376
1405
 
@@ -12,4 +12,4 @@ function verifyPopSignature(popo, spkiBytes, preimage) {
12
12
  return _seam.verify(popo.algorithmIdentifier, popo.signature, spkiBytes, preimage);
13
13
  }
14
14
 
15
- module.exports = { setEngine: _seam.setEngine, verifyPopSignature: verifyPopSignature };
15
+ module.exports = Object.freeze({ setEngine: _seam.setEngine, verifyPopSignature: verifyPopSignature });
package/lib/csr-verify.js CHANGED
@@ -13,4 +13,4 @@ function verifyCsrSignature(parsed) {
13
13
  parsed.subjectPublicKeyInfo.bytes, parsed.certificationRequestInfoBytes);
14
14
  }
15
15
 
16
- module.exports = { setEngine: _seam.setEngine, verifyCsrSignature: verifyCsrSignature };
16
+ module.exports = Object.freeze({ setEngine: _seam.setEngine, verifyCsrSignature: verifyCsrSignature });
package/lib/ct.js CHANGED
@@ -2253,7 +2253,7 @@ async function fetchLogList(opts) {
2253
2253
  });
2254
2254
  }
2255
2255
 
2256
- module.exports = {
2256
+ module.exports = intrinsic.freeze({
2257
2257
  parseSctList: parseSctList,
2258
2258
  reconstructSignedData: reconstructSignedData,
2259
2259
  verifySct: verifySct,
@@ -2276,4 +2276,4 @@ module.exports = {
2276
2276
  addPreChain: addPreChain,
2277
2277
  HASH_ALGORITHMS: HASH_ALGORITHMS,
2278
2278
  SIGNATURE_ALGORITHMS: SIGNATURE_ALGORITHMS,
2279
- };
2279
+ });
@@ -73,4 +73,4 @@ function validateSpki(spkiBytes, crv, E, code) {
73
73
  }
74
74
  }
75
75
 
76
- module.exports = { validate: validate, validateSpki: validateSpki };
76
+ module.exports = Object.freeze({ validate: validate, validateSpki: validateSpki });
package/lib/est.js CHANGED
@@ -287,7 +287,7 @@ function _findMultipartMarks(text, boundary) {
287
287
  if (lsN !== -1) { var r1 = _matchDelimAt(text, lsN, boundary); if (r1) { found = r1; foundAt = p; break; } }
288
288
  }
289
289
  if (!found) break;
290
- marks[marks.length] = { at: foundAt, bodyStart: found.end, close: found.close };
290
+ guard.list.append(marks, { at: foundAt, bodyStart: found.end, close: found.close });
291
291
  searchStart = found.end === foundAt ? found.end + 1 : found.end;
292
292
  }
293
293
  return marks;
@@ -328,9 +328,9 @@ function _splitCrlf(s) {
328
328
  var nlLen = 0;
329
329
  if (_charCodeAt(s, i) === 0x0d && i + 1 < n && _charCodeAt(s, i + 1) === 0x0a) nlLen = 2;
330
330
  else if (_charCodeAt(s, i) === 0x0a) nlLen = 1;
331
- if (nlLen > 0) { out[out.length] = _strSlice(s, last, i); i += nlLen; last = i; } else i += 1;
331
+ if (nlLen > 0) { guard.list.append(out, _strSlice(s, last, i)); i += nlLen; last = i; } else i += 1;
332
332
  }
333
- out[out.length] = _strSlice(s, last, n);
333
+ guard.list.append(out, _strSlice(s, last, n));
334
334
  return out;
335
335
  }
336
336
 
@@ -22,6 +22,26 @@ function deferred(body) {
22
22
  catch (e) { return _reject(_Promise, e); }
23
23
  }
24
24
 
25
+ // @internal
26
+ /** @internal A continuation taken from the capture, for a module that holds the guards rather than
27
+ * the intrinsic captures directly. `p.then(f)` reads `then` off the promise at the call, so a
28
+ * replacement settles the chain without running `f`, and `f` is where a step's result becomes the
29
+ * next step's input. */
30
+ // @enforced-by behavioral -- the RED vectors live with each consumer's own verdict
31
+ function chain(p, onOk, onFail) {
32
+ return _intrinsic.chain(p, onOk, onFail);
33
+ }
34
+
35
+ // @internal
36
+ /** @internal Run `body` once the work settles, either way, and pass the outcome through unchanged.
37
+ * `Promise.prototype.finally` is not this: it calls the receiver's own `then`, which is the live
38
+ * method, so a replacement there settles the chain with a value of its own AND skips the callback.
39
+ * Cleanup that wipes key material is exactly the callback that must not be skipped. */
40
+ // @enforced-by behavioral -- each consumer's RED vector drives its own cleanup
41
+ function cleanup(p, body) {
42
+ return _intrinsic.chain(p, function (out) { body(); return out; }, function (e) { body(); throw e; });
43
+ }
44
+
25
45
  // @internal
26
46
  // @enforced-by behavioral -- a RED vector in each client suite refuses a transport yielding no thenable
27
47
  function awaited(value, E, code, label) {
@@ -96,4 +116,5 @@ function bounded(value, ms, E, code, label) {
96
116
  });
97
117
  }
98
118
 
99
- module.exports = _intrinsic.freeze({ deferred: deferred, awaited: awaited, invoked: invoked, bounded: bounded });
119
+ module.exports = _intrinsic.freeze({ deferred: deferred, awaited: awaited, invoked: invoked, bounded: bounded,
120
+ chain: chain, cleanup: cleanup });
@@ -34,7 +34,6 @@ var _mapForEach = intrinsic.uncurry(Map.prototype.forEach);
34
34
  var _String = intrinsic.String;
35
35
  var _Date = intrinsic.Date;
36
36
  var _apply = intrinsic.apply;
37
- var _promiseFinally = intrinsic.promiseFinally;
38
37
  var _ArrayBuffer = intrinsic.ArrayBuffer;
39
38
  var _Uint8Array = intrinsic.Uint8Array;
40
39
  var _DataView = intrinsic.DataView;
@@ -559,10 +558,14 @@ function fixArguments(ErrorClass, code, args) {
559
558
  // @enforced-by behavioral -- an arrangement of two calls has no rename-proof shape to detect. The
560
559
  function fixedCall(ErrorClass, code, args, body) {
561
560
  var handle = null;
562
- return _promiseFinally(async.deferred(function () {
561
+ /** @internal The release is attached on BOTH outcomes rather than through `finally`, which calls
562
+ * the receiver's own `then` and so reads the live method: a replacement there settles the chain
563
+ * with a value of its own AND skips this callback, so the fixed views stay pinned. */
564
+ var ran = async.deferred(function () {
563
565
  handle = fixArguments(ErrorClass, code, args);
564
566
  return _apply(body, null, handle.values);
565
- }), function () { if (handle) handle.release(); });
567
+ });
568
+ return async.cleanup(ran, function () { if (handle) handle.release(); });
566
569
  }
567
570
 
568
571
  /**
@@ -69,7 +69,7 @@ function assertCanonicalOid(str, E, code, label, boundsCode, countCode) {
69
69
  }
70
70
  if (boundsCode === null) return str;
71
71
  var bcode = boundsCode === undefined ? code : boundsCode;
72
- var parts = _strSplit(str, ".");
72
+ var parts = intrinsic.splitChar(str, 46);
73
73
  if (parts.length - 1 > constants.LIMITS.OID_MAX_SUBIDENTIFIERS) {
74
74
  throw E(countCode || bcode, who + " carries more than " + constants.LIMITS.OID_MAX_SUBIDENTIFIERS + " sub-identifiers");
75
75
  }