node-opcua-pki 6.7.0 → 6.7.2

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.
package/dist/index.js CHANGED
@@ -1204,10 +1204,28 @@ var configurationFileSimpleTemplate = simple_config_template_cnf_default;
1204
1204
  var fsWriteFile = import_node_fs9.default.promises.writeFile;
1205
1205
  function getOrComputeInfo(entry) {
1206
1206
  if (!entry.info) {
1207
- entry.info = (0, import_node_opcua_crypto5.exploreCertificate)(entry.certificate);
1207
+ entry.info = exploreCertificateCached(entry.certificate);
1208
1208
  }
1209
1209
  return entry.info;
1210
1210
  }
1211
+ var EXPLORE_CACHE_MAX = 8;
1212
+ var _exploreCache = /* @__PURE__ */ new Map();
1213
+ function exploreCertificateCached(certificate) {
1214
+ const key = (0, import_node_opcua_crypto5.makeSHA1Thumbprint)(certificate).toString("hex");
1215
+ const cached = _exploreCache.get(key);
1216
+ if (cached) {
1217
+ _exploreCache.delete(key);
1218
+ _exploreCache.set(key, cached);
1219
+ return cached;
1220
+ }
1221
+ const info = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
1222
+ _exploreCache.set(key, info);
1223
+ if (_exploreCache.size > EXPLORE_CACHE_MAX) {
1224
+ const oldest = _exploreCache.keys().next().value;
1225
+ if (oldest) _exploreCache.delete(oldest);
1226
+ }
1227
+ return info;
1228
+ }
1211
1229
  var VerificationStatus = /* @__PURE__ */ ((VerificationStatus2) => {
1212
1230
  VerificationStatus2["BadCertificateInvalid"] = "BadCertificateInvalid";
1213
1231
  VerificationStatus2["BadSecurityChecksFailed"] = "BadSecurityChecksFailed";
@@ -1238,7 +1256,7 @@ var forbiddenChars = /[\x00-\x1F<>:"/\\|?*]/g;
1238
1256
  function buildIdealCertificateName(certificate) {
1239
1257
  const fingerprint = makeFingerprint(certificate);
1240
1258
  try {
1241
- const commonName = (0, import_node_opcua_crypto5.exploreCertificate)(certificate).tbsCertificate.subject.commonName || "";
1259
+ const commonName = exploreCertificateCached(certificate).tbsCertificate.subject.commonName || "";
1242
1260
  const sanitizedCommonName = commonName.replace(forbiddenChars, "_");
1243
1261
  return `${sanitizedCommonName}[${fingerprint}]`;
1244
1262
  } catch (_err) {
@@ -1255,14 +1273,14 @@ function isSelfSigned2(info) {
1255
1273
  return info.tbsCertificate.extensions?.subjectKeyIdentifier === info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;
1256
1274
  }
1257
1275
  function isSelfSigned3(certificate) {
1258
- const info = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
1276
+ const info = exploreCertificateCached(certificate);
1259
1277
  return isSelfSigned2(info);
1260
1278
  }
1261
1279
  function findIssuerCertificateInChain(certificate, chain) {
1262
1280
  if (!certificate) {
1263
1281
  return null;
1264
1282
  }
1265
- const certInfo = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
1283
+ const certInfo = exploreCertificateCached(certificate);
1266
1284
  if (isSelfSigned2(certInfo)) {
1267
1285
  return certificate;
1268
1286
  }
@@ -1272,7 +1290,7 @@ function findIssuerCertificateInChain(certificate, chain) {
1272
1290
  return null;
1273
1291
  }
1274
1292
  const potentialIssuers = chain.filter((c) => {
1275
- const info = (0, import_node_opcua_crypto5.exploreCertificate)(c);
1293
+ const info = exploreCertificateCached(c);
1276
1294
  return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;
1277
1295
  });
1278
1296
  if (potentialIssuers.length === 1) {
@@ -1508,7 +1526,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
1508
1526
  }
1509
1527
  const chain = (0, import_node_opcua_crypto5.split_der)(certificate);
1510
1528
  debugLog("NB CERTIFICATE IN CHAIN = ", chain.length);
1511
- const info = (0, import_node_opcua_crypto5.exploreCertificate)(chain[0]);
1529
+ const info = exploreCertificateCached(chain[0]);
1512
1530
  let hasValidIssuer = false;
1513
1531
  let hasTrustedIssuer = false;
1514
1532
  const hasIssuerKey = info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;
@@ -1785,7 +1803,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
1785
1803
  await this.#readCertificates();
1786
1804
  }
1787
1805
  async withLock2(action) {
1788
- const lockFileName = import_node_path6.default.join(this.rootDir, "mutex.lock");
1806
+ const lockFileName = import_node_path6.default.join(this.rootDir, "mutex");
1789
1807
  return (0, import_global_mutex.withLock)({ fileToLock: lockFileName }, async () => {
1790
1808
  return await action();
1791
1809
  });
@@ -1996,7 +2014,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
1996
2014
  * @param target - "issuers", "trusted", or "all" (default "all")
1997
2015
  */
1998
2016
  async removeRevocationListsForIssuer(issuerCertificate, target = "all") {
1999
- const issuerInfo = (0, import_node_opcua_crypto5.exploreCertificate)(issuerCertificate);
2017
+ const issuerInfo = exploreCertificateCached(issuerCertificate);
2000
2018
  const issuerFingerprint = issuerInfo.tbsCertificate.subjectFingerPrint;
2001
2019
  const processIndex = async (index) => {
2002
2020
  const crlData = index.get(issuerFingerprint);
@@ -2042,7 +2060,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2042
2060
  const certificates = (0, import_node_opcua_crypto5.split_der)(certificateChain);
2043
2061
  const leafCertificate = certificates[0];
2044
2062
  try {
2045
- (0, import_node_opcua_crypto5.exploreCertificate)(leafCertificate);
2063
+ exploreCertificateCached(leafCertificate);
2046
2064
  } catch (_err) {
2047
2065
  return "BadCertificateInvalid" /* BadCertificateInvalid */;
2048
2066
  }
@@ -2102,7 +2120,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2102
2120
  *
2103
2121
  */
2104
2122
  async findIssuerCertificate(certificate) {
2105
- const certInfo = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
2123
+ const certInfo = exploreCertificateCached(certificate);
2106
2124
  if (isSelfSigned2(certInfo)) {
2107
2125
  return certificate;
2108
2126
  }
@@ -2183,7 +2201,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2183
2201
  });
2184
2202
  }
2185
2203
  #findAssociatedCRLs(issuerCertificate) {
2186
- const issuerCertificateInfo = (0, import_node_opcua_crypto5.exploreCertificate)(issuerCertificate);
2204
+ const issuerCertificateInfo = exploreCertificateCached(issuerCertificate);
2187
2205
  const key = issuerCertificateInfo.tbsCertificate.subjectFingerPrint;
2188
2206
  return this.#thumbs.issuersCrl.get(key) ?? this.#thumbs.crl.get(key) ?? null;
2189
2207
  }
@@ -2217,7 +2235,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2217
2235
  if (!crls) {
2218
2236
  return "BadCertificateRevocationUnknown" /* BadCertificateRevocationUnknown */;
2219
2237
  }
2220
- const certInfo = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
2238
+ const certInfo = exploreCertificateCached(certificate);
2221
2239
  const serialNumber = certInfo.tbsCertificate.serialNumber || certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.serial || "";
2222
2240
  const key = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.authorityCertIssuerFingerPrint || "<unknown>";
2223
2241
  const crl2 = this.#thumbs.crl.get(key) ?? null;
@@ -2284,22 +2302,31 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2284
2302
  ...usePolling ? { interval: pollingInterval } : {},
2285
2303
  persistent: false
2286
2304
  };
2287
- const createUnreffedWatcher = (folder) => {
2288
- const capturedHandles = [];
2289
- const origWatch = import_node_fs9.default.watch;
2290
- import_node_fs9.default.watch = ((...args) => {
2291
- const handle = origWatch.apply(import_node_fs9.default, args);
2292
- capturedHandles.push(handle);
2293
- return handle;
2305
+ const allCapturedHandles = [];
2306
+ const origWatch = import_node_fs9.default.watch;
2307
+ let watcherReadyCount = 0;
2308
+ const totalWatchers = 5;
2309
+ import_node_fs9.default.watch = ((...args) => {
2310
+ const handle = origWatch.apply(import_node_fs9.default, args);
2311
+ handle.setMaxListeners(handle.getMaxListeners() + 1);
2312
+ handle.on("error", () => {
2294
2313
  });
2314
+ allCapturedHandles.push(handle);
2315
+ return handle;
2316
+ });
2317
+ const createUnreffedWatcher = (folder) => {
2318
+ const startIdx = allCapturedHandles.length;
2295
2319
  const w = import_chokidar.default.watch(folder, chokidarOptions);
2296
2320
  const unreffAll = () => {
2297
- import_node_fs9.default.watch = origWatch;
2298
- for (const h of capturedHandles) {
2299
- h.unref();
2321
+ for (let i = startIdx; i < allCapturedHandles.length; i++) {
2322
+ allCapturedHandles[i].unref();
2323
+ }
2324
+ watcherReadyCount++;
2325
+ if (watcherReadyCount >= totalWatchers) {
2326
+ import_node_fs9.default.watch = origWatch;
2300
2327
  }
2301
2328
  };
2302
- return { w, capturedHandles, unreffAll };
2329
+ return { w, capturedHandles: allCapturedHandles.slice(startIdx), unreffAll };
2303
2330
  };
2304
2331
  await Promise.all([
2305
2332
  this.#scanCertFolder(this.trustedFolder, this.#thumbs.trusted),
@@ -2328,7 +2355,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2328
2355
  const stat = await import_node_fs9.default.promises.stat(filename);
2329
2356
  if (!stat.isFile()) continue;
2330
2357
  const certificate = await (0, import_node_opcua_crypto5.readCertificateAsync)(filename);
2331
- const info = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
2358
+ const info = exploreCertificateCached(certificate);
2332
2359
  const fingerprint = makeFingerprint(certificate);
2333
2360
  index.set(fingerprint, { certificate, filename, info });
2334
2361
  this.#filenameToHash.set(filename, fingerprint);
@@ -2361,6 +2388,9 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2361
2388
  */
2362
2389
  #startCrlWatcher(folder, index, createUnreffedWatcher, store) {
2363
2390
  const { w, unreffAll } = createUnreffedWatcher(folder);
2391
+ w.on("error", (err) => {
2392
+ debugLog(`chokidar CRL watcher error on ${folder}:`, err);
2393
+ });
2364
2394
  let ready = false;
2365
2395
  w.on("unlink", (filename) => {
2366
2396
  for (const [key, data] of index.entries()) {
@@ -2396,6 +2426,9 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2396
2426
  */
2397
2427
  #startWatcher(folder, index, createUnreffedWatcher, store) {
2398
2428
  const { w, unreffAll } = createUnreffedWatcher(folder);
2429
+ w.on("error", (err) => {
2430
+ debugLog(`chokidar cert watcher error on ${folder}:`, err);
2431
+ });
2399
2432
  let ready = false;
2400
2433
  w.on("unlink", (filename) => {
2401
2434
  debugLog(import_chalk6.default.cyan(`unlink in folder ${folder}`), filename);
@@ -2409,7 +2442,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2409
2442
  debugLog(import_chalk6.default.cyan(`add in folder ${folder}`), filename);
2410
2443
  try {
2411
2444
  const certificate = (0, import_node_opcua_crypto5.readCertificate)(filename);
2412
- const info = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
2445
+ const info = exploreCertificateCached(certificate);
2413
2446
  const fingerprint = makeFingerprint(certificate);
2414
2447
  const isNew = !index.has(fingerprint);
2415
2448
  index.set(fingerprint, { certificate, filename, info });
@@ -2437,7 +2470,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
2437
2470
  if (oldHash && oldHash !== newFingerprint) {
2438
2471
  index.delete(oldHash);
2439
2472
  }
2440
- index.set(newFingerprint, { certificate, filename: changedPath, info: (0, import_node_opcua_crypto5.exploreCertificate)(certificate) });
2473
+ index.set(newFingerprint, { certificate, filename: changedPath, info: exploreCertificateCached(certificate) });
2441
2474
  this.#filenameToHash.set(changedPath, newFingerprint);
2442
2475
  this.emit("certificateChange", { store, certificate, fingerprint: newFingerprint, filename: changedPath });
2443
2476
  } catch (err) {