@blamejs/pki 0.8.60 → 0.9.0

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 (59) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +7 -0
  3. package/index.js +55 -26
  4. package/lib/acme.js +5 -5
  5. package/lib/asn1-der.js +1 -1
  6. package/lib/attrcert-sign.js +2 -2
  7. package/lib/cbor-det.js +4 -1
  8. package/lib/cmc-build.js +15 -10
  9. package/lib/cmp-build.js +5 -5
  10. package/lib/cmp-session.js +6 -3
  11. package/lib/cmp-verify.js +1 -1
  12. package/lib/cms-compress.js +5 -2
  13. package/lib/cms-decrypt.js +17 -17
  14. package/lib/cms-digest.js +2 -3
  15. package/lib/cms-encrypt.js +17 -18
  16. package/lib/cms-sign.js +2 -2
  17. package/lib/composite-kem.js +28 -29
  18. package/lib/crl-sign.js +3 -3
  19. package/lib/crmf-sign.js +12 -18
  20. package/lib/csr-sign.js +1 -1
  21. package/lib/ct.js +25 -22
  22. package/lib/est.js +12 -12
  23. package/lib/framework-error.js +1 -1
  24. package/lib/guard-bytes.js +1 -1
  25. package/lib/guard-crypto.js +506 -14
  26. package/lib/guard-limits.js +3 -2
  27. package/lib/guard-secret.js +3 -2
  28. package/lib/hpke.js +26 -26
  29. package/lib/http-digest.js +5 -7
  30. package/lib/http-retry-after.js +4 -1
  31. package/lib/http-transport.js +6 -6
  32. package/lib/inspect.js +9 -4
  33. package/lib/jose.js +3 -3
  34. package/lib/key.js +41 -29
  35. package/lib/merkle.js +4 -4
  36. package/lib/ocsp.js +3 -4
  37. package/lib/path-validate.js +3 -3
  38. package/lib/pbes2.js +14 -11
  39. package/lib/pkcs12-build.js +10 -11
  40. package/lib/pki-build.js +3 -3
  41. package/lib/scep.js +8 -9
  42. package/lib/schema-engine.js +12 -12
  43. package/lib/schema-pkix.js +12 -12
  44. package/lib/schema-tsp.js +3 -3
  45. package/lib/shbs.js +3 -6
  46. package/lib/sign-scheme.js +4 -4
  47. package/lib/sigstore.js +10 -10
  48. package/lib/smime.js +12 -9
  49. package/lib/tlog.js +5 -4
  50. package/lib/tls-cert-compress.js +3 -3
  51. package/lib/tsp-sign.js +6 -6
  52. package/lib/tuf.js +6 -5
  53. package/lib/validator-cose.js +2 -2
  54. package/lib/webauthn-mds.js +4 -8
  55. package/lib/webauthn.js +5 -12
  56. package/lib/webcrypto.js +61 -46
  57. package/lib/x509-sign.js +3 -3
  58. package/package.json +1 -1
  59. package/sbom.cdx.json +6 -6
package/lib/ct.js CHANGED
@@ -39,8 +39,8 @@
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");
43
+ var _create = require("./guard-intrinsic").create;
44
44
  var constants = require("./constants.js");
45
45
  var frameworkError = require("./framework-error.js");
46
46
  var guard = require("./guard-all.js");
@@ -358,7 +358,7 @@ function _u24Bytes(n) {
358
358
  var _X509_ENTRY_KEYS = intrinsic.assign(intrinsic.create(null), { entryType: 1, leafCert: 1 });
359
359
  var _PRECERT_ENTRY_KEYS = intrinsic.assign(intrinsic.create(null), { entryType: 1, tbsCertificate: 1, issuerKeyHash: 1 });
360
360
  function reconstructSignedData(entry, sct) {
361
- entry = entry || {};
361
+ entry = entry || _create(null);
362
362
  if (typeof entry !== "object") throw new CtError("ct/bad-input", "the log entry must be an object { entryType, ... } (RFC 6962 sec. 3.1)");
363
363
  var entryType = entry.entryType;
364
364
  if (entryType !== 0 && entryType !== 1) {
@@ -494,7 +494,7 @@ async function verifySct(entry, sct, logPublicKey) {
494
494
  throw new CtError("ct/log-id-mismatch", "the SCT logId does not match SHA-256 of the provided log key (RFC 6962 sec. 3.2)");
495
495
  }
496
496
  }
497
- var sigInfo = rec.signatureAlgorithm || {};
497
+ var sigInfo = rec.signatureAlgorithm || _create(null);
498
498
  var hashName = CT_HASH[sigInfo.hashName];
499
499
  if (!hashName) throw new CtError("ct/unsupported-algorithm", "unsupported SCT hash algorithm " + JSON.stringify(sigInfo.hashName) + " (RFC 6962 sec. 2.1.4 mandates sha256)");
500
500
  var alg = _spkiAlg(spki);
@@ -605,11 +605,14 @@ function encodeSctList(scts) {
605
605
  function _logKeyMaterial(logKey) {
606
606
  try {
607
607
  var keyObj;
608
- if (logKey && typeof logKey === "object" && logKey.asymmetricKeyType) keyObj = logKey;
609
- else if (Buffer.isBuffer(logKey)) keyObj = nodeCrypto.createPrivateKey({ key: logKey, format: "der", type: "pkcs8" });
610
- else keyObj = nodeCrypto.createPrivateKey(logKey);
611
- if (keyObj.type !== "private") throw new CtError("ct/bad-input", "signSct requires the CT log PRIVATE key");
612
- return { pkcs8: keyObj.export({ type: "pkcs8", format: "der" }), spki: nodeCrypto.createPublicKey(keyObj).export({ type: "spki", format: "der" }) };
608
+ if (guard.crypto.keyTypeOf(logKey)) keyObj = logKey;
609
+ else if (Buffer.isBuffer(logKey)) keyObj = guard.crypto.privateKey({ key: logKey, format: "der", type: "pkcs8" });
610
+ else keyObj = guard.crypto.privateKey(logKey);
611
+ if (guard.crypto.keyKind(keyObj) !== "private") throw new CtError("ct/bad-input", "signSct requires the CT log PRIVATE key");
612
+ return {
613
+ pkcs8: guard.crypto.exportKey(keyObj, { type: "pkcs8", format: "der" }),
614
+ spki: guard.crypto.exportKey(guard.crypto.publicKey(keyObj), { type: "spki", format: "der" }),
615
+ };
613
616
  } catch (e) {
614
617
  if (e instanceof CtError) throw e;
615
618
  throw new CtError("ct/bad-input", "the CT log private key could not be loaded", e);
@@ -725,7 +728,7 @@ function _parseLog(log, operatorName) {
725
728
  var statedId = guard.encoding.base64(log.log_id, 64, _ctErr, "ct/bad-log-list", "the CT log id");
726
729
  if (statedId.length !== 32) throw _ctErr("ct/bad-log-list", "a CT log_id must be 32 bytes (SHA-256), got " + statedId.length);
727
730
  _spkiAlg(spki);
728
- var logId = nodeCrypto.createHash("sha256").update(spki).digest();
731
+ var logId = guard.crypto.digest("sha256", spki);
729
732
  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)");
730
733
  return guard.verdict.of({
731
734
  logId: logId, logIdHex: logId.toString("hex"), key: spki,
@@ -897,7 +900,7 @@ function _classifyLog(sct, logList, entry, opts) {
897
900
  }
898
901
 
899
902
  async function verifySctWithLogList(entry, sct, logList, opts) {
900
- opts = opts || {};
903
+ opts = opts || _create(null);
901
904
  var c = _classifyLog(sct, logList, entry, opts);
902
905
  if (c.status !== "ok") throw _ctErr(c.code, c.message);
903
906
  /** @internal Read before the verify, so the timestamp the verdict states is the one the signature covered.
@@ -1111,7 +1114,7 @@ function x509CertEntry(cert, issuer) {
1111
1114
  if (k !== wrapIdx) { intrinsic.append(tbsChildren, tbs.children[k].bytes); continue; }
1112
1115
  if (kept.length > 0) intrinsic.append(tbsChildren, asn1.build.explicit(3, asn1.build.sequence(kept)));
1113
1116
  }
1114
- var issuerKeyHash = nodeCrypto.createHash("sha256").update(issSpki).digest();
1117
+ var issuerKeyHash = guard.crypto.digest("sha256", issSpki);
1115
1118
  return { entryType: 1, tbsCertificate: asn1.build.sequence(tbsChildren), issuerKeyHash: issuerKeyHash };
1116
1119
  }
1117
1120
 
@@ -1247,7 +1250,7 @@ function _assertTransport(opts) {
1247
1250
  * `Symbol.split` is part of that operation. The token decides which parser a log's response body is
1248
1251
  * handed to. */
1249
1252
  function _fetchCtypeToken(headers) {
1250
- var raw = intrinsic.String((headers || {})["content-type"] || "");
1253
+ var raw = intrinsic.String((headers || _create(null))["content-type"] || "");
1251
1254
  var parts = intrinsic.splitChar(raw, 59);
1252
1255
  return _toLowerCase(_ctTrim(parts.length ? parts[0] : ""));
1253
1256
  }
@@ -1277,7 +1280,7 @@ function _fetchBody(transport, url, req, label) {
1277
1280
  if (req.body !== undefined) request.body = req.body;
1278
1281
  return transport(request);
1279
1282
  }).then(function (res) {
1280
- res = res || {};
1283
+ res = res || _create(null);
1281
1284
  var h = intrinsic.create(null);
1282
1285
  guard.identifier.optionNames(res.headers).forEach(function (k) { h[k.toLowerCase()] = res.headers[k]; });
1283
1286
  var body = guard.bytes.isByteSource(res.body)
@@ -1579,7 +1582,7 @@ function _uintField(obj, name, code, label) {
1579
1582
  var _STH_KEYS = intrinsic.assign(intrinsic.create(null),
1580
1583
  { timestamp: 1, treeSize: 1, rootHash: 1, signature: 1, raw: 1, then: 1 });
1581
1584
  function sthSignedData(sth) {
1582
- sth = sth || {};
1585
+ sth = sth || _create(null);
1583
1586
  guard.identifier.assertKnownKeys(sth, _STH_KEYS, _ctErr, "ct/bad-input", "unknown sth field ");
1584
1587
  var ts = guard.range.uint64(sth.timestamp, _ctErr, "ct/bad-input", "sth.timestamp");
1585
1588
  var size = guard.range.uint64(sth.treeSize, _ctErr, "ct/bad-input", "sth.treeSize");
@@ -1625,7 +1628,7 @@ function sthSignedData(sth) {
1625
1628
  * // -> true
1626
1629
  */
1627
1630
  async function verifySth(sth, logKey) {
1628
- sth = sth || {};
1631
+ sth = sth || _create(null);
1629
1632
  var signature = _toBuffer(sth.signature, "sth.signature");
1630
1633
  var signedData = sthSignedData({ timestamp: sth.timestamp, treeSize: sth.treeSize, rootHash: sth.rootHash });
1631
1634
  return await _verifyDigitallySigned(signedData, signature, logKey, "the signed tree head");
@@ -1666,7 +1669,7 @@ async function verifySth(sth, logKey) {
1666
1669
  * sth.treeSize; // -> 3n
1667
1670
  */
1668
1671
  async function getSth(opts) {
1669
- var door = _clientDoor(opts || {}, "logKey");
1672
+ var door = _clientDoor(opts || _create(null), "logKey");
1670
1673
  opts = door.o;
1671
1674
  /** @internal ONE read of the option, and the presence check and the copy both decide from it. Reading
1672
1675
  * it twice let an accessor answer the two separately: a non-null value for the check and an
@@ -1725,7 +1728,7 @@ async function getSth(opts) {
1725
1728
  * p.verified; // -> true
1726
1729
  */
1727
1730
  async function getProofByHash(opts) {
1728
- var door = _clientDoor(opts || {}, null);
1731
+ var door = _clientDoor(opts || _create(null), null);
1729
1732
  opts = door.o;
1730
1733
  var sth = _assertSth(opts.sth, "opts.sth");
1731
1734
  /** @internal Copied for the reason the tree head is: it is sent on the wire and then folded against the
@@ -1781,7 +1784,7 @@ async function getProofByHash(opts) {
1781
1784
  * c.verified; // -> true
1782
1785
  */
1783
1786
  async function getSthConsistency(opts) {
1784
- var door = _clientDoor(opts || {}, null);
1787
+ var door = _clientDoor(opts || _create(null), null);
1785
1788
  opts = door.o;
1786
1789
  var oldSth = _assertSth(opts.oldSth, "opts.oldSth");
1787
1790
  var newSth = _assertSth(opts.newSth, "opts.newSth");
@@ -1839,7 +1842,7 @@ async function getSthConsistency(opts) {
1839
1842
  * e.entries[0].leafInput; // -> <Buffer ...>
1840
1843
  */
1841
1844
  async function getEntries(opts) {
1842
- var door = _clientDoor(opts || {}, null);
1845
+ var door = _clientDoor(opts || _create(null), null);
1843
1846
  opts = door.o;
1844
1847
  var start = guard.range.uint64(opts.start, _ctErr, "ct/bad-input", "opts.start");
1845
1848
  var end = guard.range.uint64(opts.end, _ctErr, "ct/bad-input", "opts.end");
@@ -1897,7 +1900,7 @@ async function getEntries(opts) {
1897
1900
  */
1898
1901
  async function getRoots(opts) {
1899
1902
  /** @internal This message carries no options of its own, so the door's record is all that is used. */
1900
- var door = _clientDoor(opts || {}, null);
1903
+ var door = _clientDoor(opts || _create(null), null);
1901
1904
  var doc = await _clientJson(door, "get-roots", "roots");
1902
1905
  return guard.verdict.of({ certificates: _b64Array(doc, "certificates", "ct/bad-roots", "roots", undefined, C.LIMITS.CT_MAX_ROOTS) });
1903
1906
  }
@@ -1980,7 +1983,7 @@ async function addPreChain(opts) {
1980
1983
  * The chain encoding, the response shape, and the refusal when the receipt does not verify are one
1981
1984
  * rule stated once. */
1982
1985
  async function _addChain(opts, message, entryType) {
1983
- var door = _clientDoor(opts || {}, "logKey");
1986
+ var door = _clientDoor(opts || _create(null), "logKey");
1984
1987
  opts = door.o;
1985
1988
  /** @internal ONE read of the option, used by the presence check here and by the copy below. Reading it
1986
1989
  * twice let an accessor answer the two separately, presenting a non-null value to the check and an
@@ -2028,7 +2031,7 @@ async function _addChain(opts, message, entryType) {
2028
2031
  ? _bufferAlloc(0) : _b64Field(doc, "extensions", "ct/bad-sct", "sct"),
2029
2032
  signature: _b64Field(doc, "signature", "ct/bad-sct", "sct"),
2030
2033
  };
2031
- var pinnedId = nodeCrypto.createHash("sha256").update(pinnedKey).digest();
2034
+ var pinnedId = guard.crypto.digest("sha256", pinnedKey);
2032
2035
  if (_bufferCompare(sct.logId, pinnedId) !== 0) {
2033
2036
  throw _ctErr("ct/sct-untrusted", "the SCT names log id " + _bufToString(sct.logId, "hex") +
2034
2037
  " where the pinned key's id is " + _bufToString(pinnedId, "hex") + " -- it is not this log's receipt");
package/lib/est.js CHANGED
@@ -533,7 +533,7 @@ function _partMediaType(contentType) {
533
533
  }
534
534
 
535
535
  function parseServerKeygenResponse(body, contentType, opts) {
536
- opts = opts || {};
536
+ opts = opts || intrinsic.create(null);
537
537
  opts = _knownOpts(opts, PARSE_SERVERKEYGEN_OPTS, "parseServerKeygenResponse");
538
538
  var parts = splitMultipartMixed(body, contentType);
539
539
  if (parts.length !== 2) throw E("est/bad-multipart", "a serverkeygen response must have exactly two parts (RFC 7030 sec. 4.4.2)");
@@ -617,7 +617,7 @@ function classifyResponse(status, headers, body, opts) {
617
617
  }
618
618
 
619
619
  function _classifyResponse(status, headers, body, opts) {
620
- opts = opts || {};
620
+ opts = opts || intrinsic.create(null);
621
621
  opts = _knownOpts(opts, CLASSIFY_OPTS, "classifyResponse");
622
622
  var op = opts.op;
623
623
  if (op !== undefined && op !== null && CLASSIFIABLE_OPS.indexOf(op) === -1) throw E("est/unsupported-operation", "unrecognized EST operation " + guard.text.showValue(op));
@@ -689,7 +689,7 @@ function _classifyResponse(status, headers, body, opts) {
689
689
  * // -> "https://ca.example/.well-known/est/cacerts"
690
690
  */
691
691
  function paths(baseUrl, opts) {
692
- opts = opts || {};
692
+ opts = opts || intrinsic.create(null);
693
693
  opts = _knownOpts(opts, PATHS_OPTS, "paths");
694
694
  var base = String(baseUrl);
695
695
  var prefix = base.slice(0, _stripTrailingSlashEnd(base)) + "/.well-known/est";
@@ -957,7 +957,7 @@ function _drive(method, url, body, headers, opts, transport, budgets) {
957
957
  function step() {
958
958
  var hopBody = (typeof body === "function" && budgets.onAttempt) ? budgets.onAttempt() : body;
959
959
  return guard.async.invoked(transport, [{ method: method, url: _urlHref(url), headers: _headersFor(url), body: hopBody, tls: _tlsFor(url), proxy: budgets.proxy, timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes }], E, "est/bad-input", "opts.transport").then(function (res) {
960
- res = res || {};
960
+ res = res || intrinsic.create(null);
961
961
  var blen = _bodyLen(res);
962
962
  if (blen > budgets.maxResponseBytes) throw E("est/response-too-large", "the response body (" + blen + " bytes) exceeds the " + budgets.maxResponseBytes + "-byte cap (RFC 7030 sec. 6)");
963
963
  var h = intrinsic.assign(intrinsic.create(null), {
@@ -1159,7 +1159,7 @@ function _certsResult(op, res, opts, csrSpki) {
1159
1159
  * r.retry && r.retryAfterSeconds; // 60
1160
1160
  */
1161
1161
  function fullcmc(baseUrl, request, opts) {
1162
- opts = opts || {};
1162
+ opts = opts || intrinsic.create(null);
1163
1163
  var der, wanted, sent;
1164
1164
  try {
1165
1165
  if (typeof opts !== "object" || Buffer.isBuffer(opts)) throw E("est/bad-input", "pki.est.fullcmc options must be an object");
@@ -1588,7 +1588,7 @@ function _enroll(op, baseUrl, csrInput, opts, proxySnap) {
1588
1588
  * r.certificates; // -> [Buffer, ...] raw, unordered
1589
1589
  */
1590
1590
  function cacerts(baseUrl, opts) {
1591
- opts = opts || {};
1591
+ opts = opts || intrinsic.create(null);
1592
1592
  var proxySnap; try { proxySnap = _snapProxy(opts); } catch (_pe) { return _rej(E("est/bad-input", "the options object could not be read", _pe)); }
1593
1593
  return _promiseResolve(_Promise, undefined).then(function () {
1594
1594
  opts = _knownOpts(opts, CACERTS_OPTS, "cacerts");
@@ -1654,7 +1654,7 @@ function cacerts(baseUrl, opts) {
1654
1654
  * bound.retry; // true
1655
1655
  */
1656
1656
  function simpleenroll(baseUrl, csrInput, opts) {
1657
- opts = opts || {};
1657
+ opts = opts || intrinsic.create(null);
1658
1658
  var proxySnap; try { proxySnap = _snapProxy(opts); } catch (_pe) { return _rej(E("est/bad-input", "the options object could not be read", _pe)); }
1659
1659
  return _promiseResolve(_Promise, undefined).then(function () {
1660
1660
  opts = _knownOpts(opts, SIMPLEENROLL_OPTS, "simpleenroll");
@@ -1694,7 +1694,7 @@ function simpleenroll(baseUrl, csrInput, opts) {
1694
1694
  * r.retry; // true
1695
1695
  */
1696
1696
  function simplereenroll(baseUrl, csrInput, opts) {
1697
- opts = opts || {};
1697
+ opts = opts || intrinsic.create(null);
1698
1698
  var proxySnap; try { proxySnap = _snapProxy(opts); } catch (_pe) { return _rej(E("est/bad-input", "the options object could not be read", _pe)); }
1699
1699
  return _promiseResolve(_Promise, undefined).then(function () {
1700
1700
  opts = _knownOpts(opts, SIMPLEREENROLL_OPTS, "simplereenroll");
@@ -1751,7 +1751,7 @@ function _assertConfidentialCipher(res) {
1751
1751
  }
1752
1752
 
1753
1753
  function _ciHeaderList(headers, name) {
1754
- headers = headers || {};
1754
+ headers = headers || intrinsic.create(null);
1755
1755
  /** @internal The header NAME a value is selected under is folded through the captured conversion on
1756
1756
  * both sides of the comparison: the match decides which header this response is read from. */
1757
1757
  var lname = _toLowerCase(name), keys = guard.identifier.optionNames(headers), parts = [];
@@ -1765,7 +1765,7 @@ function _ciHeaderList(headers, name) {
1765
1765
  }
1766
1766
 
1767
1767
  function _ciHeader(headers, name) {
1768
- headers = headers || {};
1768
+ headers = headers || intrinsic.create(null);
1769
1769
  var lname = _toLowerCase(name), keys = guard.identifier.optionNames(headers), found = null, n = 0;
1770
1770
  for (var i = 0; i < keys.length; i++) {
1771
1771
  if (_toLowerCase(keys[i]) !== lname) continue;
@@ -1854,7 +1854,7 @@ async function _serverkeygenResult(res, opts, derived) {
1854
1854
  * r.retry; // true -- a 202 is surfaced, never slept
1855
1855
  */
1856
1856
  function serverkeygen(baseUrl, csrInput, opts) {
1857
- opts = opts || {};
1857
+ opts = opts || intrinsic.create(null);
1858
1858
  var proxySnap; try { proxySnap = _snapProxy(opts); } catch (_pe) { return _rej(E("est/bad-input", "the options object could not be read", _pe)); }
1859
1859
  return _promiseResolve(_Promise, undefined).then(function () {
1860
1860
  opts = _knownOpts(opts, SERVERKEYGEN_OPTS, "serverkeygen");
@@ -1916,7 +1916,7 @@ function _csrattrsResult(res, opts) {
1916
1916
  * r.available; // false -- a 404 is "no CSR-attributes policy available"
1917
1917
  */
1918
1918
  function csrattrs(baseUrl, opts) {
1919
- opts = opts || {};
1919
+ opts = opts || intrinsic.create(null);
1920
1920
  var proxySnap; try { proxySnap = _snapProxy(opts); } catch (_pe) { return _rej(E("est/bad-input", "the options object could not be read", _pe)); }
1921
1921
  return _promiseResolve(_Promise, undefined).then(function () {
1922
1922
  opts = _knownOpts(opts, CSRATTRS_OPTS, "csrattrs");
@@ -122,7 +122,7 @@ function defineClass(name, opts) {
122
122
  if (typeof name !== "string" || name.length === 0) {
123
123
  throw new TypeError("defineClass: name must be a non-empty string");
124
124
  }
125
- opts = opts || {};
125
+ opts = opts || intrinsic.create(null);
126
126
  var withCause = !!opts.withCause;
127
127
  var flagKey = "is" + name;
128
128
 
@@ -281,7 +281,7 @@ function snapshotSource(input, ErrorClass, code, label) {
281
281
  * the budget rather than the shape of the input. The figure is far above any real caller value: an
282
282
  * options bag or a JWK is tens of nodes, and a certificate chain passed as an anchor list is thousands. */
283
283
  function snapshotDeep(value, ErrorClass, code, label, opts) {
284
- var o = opts || {};
284
+ var o = opts || _create(null);
285
285
  var cap = o.maxDepth == null ? 64 : o.maxDepth;
286
286
  var maxNodes = o.maxNodes == null ? constants.LIMITS.DEEP_COPY_MAX_NODES : o.maxNodes;
287
287
  return _deep(value, ErrorClass, code, label, cap, 0, o.collect || null, { n: 0, max: maxNodes });