node-opcua-pki 6.21.0 → 6.22.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.
package/dist/core.mjs CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  defaultSubject,
8
8
  escapeOpensslConfDoubleQuoted,
9
9
  renderCaConfig
10
- } from "./chunk-2HTNH73K.mjs";
10
+ } from "./chunk-EQ4DGI4M.mjs";
11
11
  export {
12
12
  CaDatabase,
13
13
  CertificateAuthorityCore,
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { PrivateKey, Certificate, SubjectOptions, DER, CertificateRevocationList } from 'node-opcua-crypto';
2
- export { PrivateKeyPassphraseRequiredError, Subject, SubjectOptions } from 'node-opcua-crypto';
3
- import { C as CaBackend, a as CertificateAuthorityCore, P as Params, b as ProcessAltNamesParam, c as CertificateAuthorityCoreOptions, K as KeySize, d as PrivateKeyPassphrase, e as PrivateKeyProvider, f as CreateSelfSignCertificateParam, F as Filename } from './core-C6faZClF.mjs';
4
- export { g as CertificateStatus, h as CreateCertificateSigningRequestOptions, i as CreateCertificateSigningRequestWithConfigOptions, j as CreateSelfSignCertificateWithConfigParam, G as GenerateKeyPairAndSignOptions, k as GenerateKeyPairAndSignPFXOptions, I as InitializeCSRResult, l as InstallCACertificateResult, m as KeyLength, N as NativeCaBackend, n as PkiBackendCapabilities, S as SignCertificateOptions, o as StartDateEndDateParam, T as Thumbprint, p as adjustApplicationUri, q as adjustDate, r as quote, s as resolvePrivateKeyPassphrase } from './core-C6faZClF.mjs';
1
+ import { IKeyOperations, PrivateKey, Certificate, SubjectOptions, DER, CertificateRevocationList } from 'node-opcua-crypto';
2
+ export { AsymmetricDecryptParams, AsymmetricSignParams, IKeyOperations, KeyMetadata, PrivateKeyPassphraseRequiredError, PrivateKeyUnavailableError, Subject, SubjectOptions } from 'node-opcua-crypto';
3
+ import { C as CaBackend, a as CertificateAuthorityCore, P as Params, b as ProcessAltNamesParam, c as CertificateAuthorityCoreOptions, K as KeySize, d as PrivateKeyPassphrase, e as PrivateKeyProvider, f as CreateSelfSignCertificateParam, F as Filename } from './core-BwqSJPHc.mjs';
4
+ export { g as CertificateStatus, h as CreateCertificateSigningRequestOptions, i as CreateCertificateSigningRequestWithConfigOptions, j as CreateSelfSignCertificateWithConfigParam, G as GenerateKeyPairAndSignOptions, k as GenerateKeyPairAndSignPFXOptions, I as InitializeCSRResult, l as InstallCACertificateResult, m as KeyLength, N as NativeCaBackend, n as PkiBackendCapabilities, S as SignCertificateOptions, o as StartDateEndDateParam, T as Thumbprint, p as adjustApplicationUri, q as adjustDate, r as isOpaqueSigner, s as quote, t as resolvePrivateKeyPassphrase } from './core-BwqSJPHc.mjs';
5
5
  import { EventEmitter } from 'node:events';
6
6
 
7
7
  /**
@@ -239,6 +239,29 @@ interface CertificateManagerOptions {
239
239
  * ignored.
240
240
  */
241
241
  privateKeyProvider?: PrivateKeyProvider;
242
+ /**
243
+ * Use a private key this manager can never read: an opaque
244
+ * {@link IKeyOperations} provider (HSM, KMS, TPM, OS keystore, ...).
245
+ *
246
+ * The distinction with `privateKeyProvider` matters: a
247
+ * `privateKeyProvider` *sources raw key material* from elsewhere and
248
+ * hands it back; `keyOperations` never reveals the key — only sign and
249
+ * decrypt operations on it. Prefer `keyOperations` whenever the key
250
+ * does not need to be exportable.
251
+ *
252
+ * When set:
253
+ * - {@link CertificateManager.getPrivateKey} and
254
+ * {@link CertificateManager.reencryptPrivateKey} throw
255
+ * `PrivateKeyUnavailableError` — there is no key material to return
256
+ * or rewrite, and no on-disk key is generated or expected;
257
+ * - {@link CertificateManager.getKeyOperations} returns this object;
258
+ * - `initialize()` fails closed if the provider cannot answer
259
+ * `getKeyMetadata()` (unreachable HSM, misconfiguration);
260
+ * - mutually exclusive with `privateKeyProvider` and
261
+ * `privateKeyPassphrase` — both describe key *material*, which an
262
+ * opaque configuration does not have.
263
+ */
264
+ keyOperations?: IKeyOperations;
242
265
  }
243
266
  /**
244
267
  * Parameters for {@link createSelfSignedCertificate}.
@@ -533,6 +556,27 @@ declare class CertificateManager extends EventEmitter {
533
556
  * authority on what the current key is.
534
557
  */
535
558
  getPrivateKey(): Promise<PrivateKey>;
559
+ /**
560
+ * True when this manager's key is opaque — configured through
561
+ * `keyOperations`, held by an HSM/KMS, never obtainable as material.
562
+ * When true, {@link getPrivateKey} throws `PrivateKeyUnavailableError`
563
+ * and {@link getKeyOperations} is the only way to use the key.
564
+ */
565
+ isPrivateKeyOpaque(): boolean;
566
+ /**
567
+ * The key as an opaque {@link IKeyOperations} — the recommended way to
568
+ * *use* the private key regardless of where it lives.
569
+ *
570
+ * Returns the configured `keyOperations` object when the key is opaque.
571
+ * Otherwise returns a stable lazy wrap over {@link getPrivateKey}: its
572
+ * methods resolve the key on first use (disk read, passphrase,
573
+ * `privateKeyProvider` — all async), so the wrap offers no synchronous
574
+ * fast path; callers that need one resolve the key themselves and build
575
+ * a `LocalKeyOperations` over it. The wrap follows key rotation: a
576
+ * `privateKeyProvider` that starts returning a different key gets a
577
+ * fresh underlying `LocalKeyOperations`.
578
+ */
579
+ getKeyOperations(): IKeyOperations;
536
580
  /**
537
581
  * Enable, disable, or rotate the passphrase protecting the on-disk
538
582
  * private key: decrypt with `oldPassphrase` (omit if the key is
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { PrivateKey, Certificate, SubjectOptions, DER, CertificateRevocationList } from 'node-opcua-crypto';
2
- export { PrivateKeyPassphraseRequiredError, Subject, SubjectOptions } from 'node-opcua-crypto';
3
- import { C as CaBackend, a as CertificateAuthorityCore, P as Params, b as ProcessAltNamesParam, c as CertificateAuthorityCoreOptions, K as KeySize, d as PrivateKeyPassphrase, e as PrivateKeyProvider, f as CreateSelfSignCertificateParam, F as Filename } from './core-C6faZClF.js';
4
- export { g as CertificateStatus, h as CreateCertificateSigningRequestOptions, i as CreateCertificateSigningRequestWithConfigOptions, j as CreateSelfSignCertificateWithConfigParam, G as GenerateKeyPairAndSignOptions, k as GenerateKeyPairAndSignPFXOptions, I as InitializeCSRResult, l as InstallCACertificateResult, m as KeyLength, N as NativeCaBackend, n as PkiBackendCapabilities, S as SignCertificateOptions, o as StartDateEndDateParam, T as Thumbprint, p as adjustApplicationUri, q as adjustDate, r as quote, s as resolvePrivateKeyPassphrase } from './core-C6faZClF.js';
1
+ import { IKeyOperations, PrivateKey, Certificate, SubjectOptions, DER, CertificateRevocationList } from 'node-opcua-crypto';
2
+ export { AsymmetricDecryptParams, AsymmetricSignParams, IKeyOperations, KeyMetadata, PrivateKeyPassphraseRequiredError, PrivateKeyUnavailableError, Subject, SubjectOptions } from 'node-opcua-crypto';
3
+ import { C as CaBackend, a as CertificateAuthorityCore, P as Params, b as ProcessAltNamesParam, c as CertificateAuthorityCoreOptions, K as KeySize, d as PrivateKeyPassphrase, e as PrivateKeyProvider, f as CreateSelfSignCertificateParam, F as Filename } from './core-BwqSJPHc.js';
4
+ export { g as CertificateStatus, h as CreateCertificateSigningRequestOptions, i as CreateCertificateSigningRequestWithConfigOptions, j as CreateSelfSignCertificateWithConfigParam, G as GenerateKeyPairAndSignOptions, k as GenerateKeyPairAndSignPFXOptions, I as InitializeCSRResult, l as InstallCACertificateResult, m as KeyLength, N as NativeCaBackend, n as PkiBackendCapabilities, S as SignCertificateOptions, o as StartDateEndDateParam, T as Thumbprint, p as adjustApplicationUri, q as adjustDate, r as isOpaqueSigner, s as quote, t as resolvePrivateKeyPassphrase } from './core-BwqSJPHc.js';
5
5
  import { EventEmitter } from 'node:events';
6
6
 
7
7
  /**
@@ -239,6 +239,29 @@ interface CertificateManagerOptions {
239
239
  * ignored.
240
240
  */
241
241
  privateKeyProvider?: PrivateKeyProvider;
242
+ /**
243
+ * Use a private key this manager can never read: an opaque
244
+ * {@link IKeyOperations} provider (HSM, KMS, TPM, OS keystore, ...).
245
+ *
246
+ * The distinction with `privateKeyProvider` matters: a
247
+ * `privateKeyProvider` *sources raw key material* from elsewhere and
248
+ * hands it back; `keyOperations` never reveals the key — only sign and
249
+ * decrypt operations on it. Prefer `keyOperations` whenever the key
250
+ * does not need to be exportable.
251
+ *
252
+ * When set:
253
+ * - {@link CertificateManager.getPrivateKey} and
254
+ * {@link CertificateManager.reencryptPrivateKey} throw
255
+ * `PrivateKeyUnavailableError` — there is no key material to return
256
+ * or rewrite, and no on-disk key is generated or expected;
257
+ * - {@link CertificateManager.getKeyOperations} returns this object;
258
+ * - `initialize()` fails closed if the provider cannot answer
259
+ * `getKeyMetadata()` (unreachable HSM, misconfiguration);
260
+ * - mutually exclusive with `privateKeyProvider` and
261
+ * `privateKeyPassphrase` — both describe key *material*, which an
262
+ * opaque configuration does not have.
263
+ */
264
+ keyOperations?: IKeyOperations;
242
265
  }
243
266
  /**
244
267
  * Parameters for {@link createSelfSignedCertificate}.
@@ -533,6 +556,27 @@ declare class CertificateManager extends EventEmitter {
533
556
  * authority on what the current key is.
534
557
  */
535
558
  getPrivateKey(): Promise<PrivateKey>;
559
+ /**
560
+ * True when this manager's key is opaque — configured through
561
+ * `keyOperations`, held by an HSM/KMS, never obtainable as material.
562
+ * When true, {@link getPrivateKey} throws `PrivateKeyUnavailableError`
563
+ * and {@link getKeyOperations} is the only way to use the key.
564
+ */
565
+ isPrivateKeyOpaque(): boolean;
566
+ /**
567
+ * The key as an opaque {@link IKeyOperations} — the recommended way to
568
+ * *use* the private key regardless of where it lives.
569
+ *
570
+ * Returns the configured `keyOperations` object when the key is opaque.
571
+ * Otherwise returns a stable lazy wrap over {@link getPrivateKey}: its
572
+ * methods resolve the key on first use (disk read, passphrase,
573
+ * `privateKeyProvider` — all async), so the wrap offers no synchronous
574
+ * fast path; callers that need one resolve the key themselves and build
575
+ * a `LocalKeyOperations` over it. The wrap follows key rotation: a
576
+ * `privateKeyProvider` that starts returning a different key gets a
577
+ * fresh underlying `LocalKeyOperations`.
578
+ */
579
+ getKeyOperations(): IKeyOperations;
536
580
  /**
537
581
  * Enable, disable, or rotate the passphrase protecting the on-disk
538
582
  * private key: decrypt with `oldPassphrase` (omit if the key is
package/dist/index.js CHANGED
@@ -38,6 +38,7 @@ __export(lib_exports, {
38
38
  NativeCaBackend: () => NativeCaBackend,
39
39
  OpenSslCaBackend: () => OpenSslCaBackend,
40
40
  PrivateKeyPassphraseRequiredError: () => import_node_opcua_crypto10.PrivateKeyPassphraseRequiredError,
41
+ PrivateKeyUnavailableError: () => import_node_opcua_crypto10.PrivateKeyUnavailableError,
41
42
  Subject: () => import_node_opcua_crypto3.Subject,
42
43
  VerificationStatus: () => VerificationStatus,
43
44
  adjustApplicationUri: () => adjustApplicationUri,
@@ -54,6 +55,7 @@ __export(lib_exports, {
54
55
  install_prerequisite: () => install_prerequisite,
55
56
  isIntermediateIssuer: () => isIntermediateIssuer,
56
57
  isIssuer: () => isIssuer,
58
+ isOpaqueSigner: () => isOpaqueSigner,
57
59
  isRootIssuer: () => isRootIssuer,
58
60
  makeFingerprint: () => makeFingerprint,
59
61
  quote: () => quote,
@@ -72,6 +74,9 @@ var import_node_assert = __toESM(require("assert"));
72
74
  function quote(str) {
73
75
  return `"${str || ""}"`;
74
76
  }
77
+ function isOpaqueSigner(privateKey) {
78
+ return typeof privateKey !== "string" && typeof privateKey.sign === "function";
79
+ }
75
80
  async function resolvePrivateKeyPassphrase(passphrase) {
76
81
  if (passphrase === void 0) {
77
82
  return void 0;
@@ -2887,8 +2892,9 @@ async function createCertificateSigningRequestAsync(certificateSigningRequestFil
2887
2892
  (0, import_node_assert6.default)(typeof certificateSigningRequestFilename === "string");
2888
2893
  const subject = params.subject ? new import_node_opcua_crypto6.Subject(params.subject).toString() : void 0;
2889
2894
  displaySubtitle("- Creating a Certificate Signing Request with subtile");
2890
- const privateKeyPem = typeof params.privateKey === "string" ? await import_node_fs9.default.promises.readFile(params.privateKey, "utf-8") : (0, import_node_opcua_crypto6.coercePrivateKeyPem)(params.privateKey);
2891
- const privateKey = await (0, import_node_opcua_crypto6.pemToPrivateKey)(privateKeyPem);
2895
+ const privateKey = isOpaqueSigner(params.privateKey) ? params.privateKey : await (0, import_node_opcua_crypto6.pemToPrivateKey)(
2896
+ typeof params.privateKey === "string" ? await import_node_fs9.default.promises.readFile(params.privateKey, "utf-8") : (0, import_node_opcua_crypto6.coercePrivateKeyPem)(params.privateKey)
2897
+ );
2892
2898
  const { csr } = await (0, import_node_opcua_crypto6.createCertificateSigningRequest)({
2893
2899
  privateKey,
2894
2900
  dns: params.dns,
@@ -2898,7 +2904,9 @@ async function createCertificateSigningRequestAsync(certificateSigningRequestFil
2898
2904
  purpose: params.purpose
2899
2905
  });
2900
2906
  await import_node_fs9.default.promises.writeFile(certificateSigningRequestFilename, csr, "utf-8");
2901
- display(`- privateKey ${typeof params.privateKey === "string" ? params.privateKey : "<in-memory>"}`);
2907
+ display(
2908
+ `- privateKey ${typeof params.privateKey === "string" ? params.privateKey : isOpaqueSigner(params.privateKey) ? "<opaque-signer>" : "<in-memory>"}`
2909
+ );
2902
2910
  display(`- certificateSigningRequestFilename ${certificateSigningRequestFilename}`);
2903
2911
  }
2904
2912
 
@@ -2925,8 +2933,9 @@ async function createSelfSignedCertificateAsync(certificate, params) {
2925
2933
  subject = subject.toString();
2926
2934
  const purpose = params.purpose;
2927
2935
  displayTitle("Generate a certificate request");
2928
- const privateKeyPem = typeof params.privateKey === "string" ? await import_node_fs10.default.promises.readFile(params.privateKey, "utf-8") : (0, import_node_opcua_crypto7.coercePrivateKeyPem)(params.privateKey);
2929
- const privateKey = await (0, import_node_opcua_crypto7.pemToPrivateKey)(privateKeyPem);
2936
+ const privateKey = isOpaqueSigner(params.privateKey) ? params.privateKey : await (0, import_node_opcua_crypto7.pemToPrivateKey)(
2937
+ typeof params.privateKey === "string" ? await import_node_fs10.default.promises.readFile(params.privateKey, "utf-8") : (0, import_node_opcua_crypto7.coercePrivateKeyPem)(params.privateKey)
2938
+ );
2930
2939
  const { cert } = await (0, import_node_opcua_crypto7.createSelfSignedCertificate)({
2931
2940
  privateKey,
2932
2941
  notBefore: params.startDate,
@@ -3231,6 +3240,9 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3231
3240
  #disableFileWatchers;
3232
3241
  #privateKeyPassphrase;
3233
3242
  #privateKeyProvider;
3243
+ #keyOperations;
3244
+ /** The stable lazy wrap handed out by {@link getKeyOperations} for non-opaque configurations. */
3245
+ #lazyLocalKeyOperations;
3234
3246
  /**
3235
3247
  * The on-disk key, decrypted once and kept for the instance's lifetime,
3236
3248
  * so the passphrase (or its resolver function) is consulted at most
@@ -3274,6 +3286,17 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3274
3286
  this.#disableFileWatchers = options.disableFileWatchers ?? process.env.OPCUA_PKI_DISABLE_FILE_WATCHERS === "true";
3275
3287
  this.#privateKeyPassphrase = options.privateKeyPassphrase;
3276
3288
  this.#privateKeyProvider = options.privateKeyProvider;
3289
+ this.#keyOperations = options.keyOperations;
3290
+ if (this.#keyOperations && this.#privateKeyProvider) {
3291
+ throw new Error(
3292
+ "CertificateManager: 'keyOperations' and 'privateKeyProvider' are mutually exclusive: one hides the key, the other sources its material"
3293
+ );
3294
+ }
3295
+ if (this.#keyOperations && this.#privateKeyPassphrase) {
3296
+ throw new Error(
3297
+ "CertificateManager: 'privateKeyPassphrase' is meaningless with 'keyOperations': there is no key material for a passphrase to protect"
3298
+ );
3299
+ }
3277
3300
  mkdirRecursiveSync(options.location);
3278
3301
  if (!import_node_fs11.default.existsSync(this.#location)) {
3279
3302
  throw new Error(`CertificateManager cannot access location ${this.#location}`);
@@ -3315,6 +3338,11 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3315
3338
  * authority on what the current key is.
3316
3339
  */
3317
3340
  async getPrivateKey() {
3341
+ if (this.#keyOperations) {
3342
+ throw new import_node_opcua_crypto8.PrivateKeyUnavailableError(
3343
+ "CertificateManager.getPrivateKey is not available when keyOperations is configured: the private key is held by the key-operations provider (HSM/KMS) and cannot be read \u2014 use getKeyOperations() instead"
3344
+ );
3345
+ }
3318
3346
  if (this.#privateKeyProvider) {
3319
3347
  return await this.#privateKeyProvider.getPrivateKey();
3320
3348
  }
@@ -3340,6 +3368,75 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3340
3368
  }
3341
3369
  /** In-flight first read of the on-disk key, so concurrent callers share one passphrase resolution. */
3342
3370
  #privateKeyPromise;
3371
+ /**
3372
+ * True when this manager's key is opaque — configured through
3373
+ * `keyOperations`, held by an HSM/KMS, never obtainable as material.
3374
+ * When true, {@link getPrivateKey} throws `PrivateKeyUnavailableError`
3375
+ * and {@link getKeyOperations} is the only way to use the key.
3376
+ */
3377
+ isPrivateKeyOpaque() {
3378
+ return !!this.#keyOperations;
3379
+ }
3380
+ /**
3381
+ * The key as an opaque {@link IKeyOperations} — the recommended way to
3382
+ * *use* the private key regardless of where it lives.
3383
+ *
3384
+ * Returns the configured `keyOperations` object when the key is opaque.
3385
+ * Otherwise returns a stable lazy wrap over {@link getPrivateKey}: its
3386
+ * methods resolve the key on first use (disk read, passphrase,
3387
+ * `privateKeyProvider` — all async), so the wrap offers no synchronous
3388
+ * fast path; callers that need one resolve the key themselves and build
3389
+ * a `LocalKeyOperations` over it. The wrap follows key rotation: a
3390
+ * `privateKeyProvider` that starts returning a different key gets a
3391
+ * fresh underlying `LocalKeyOperations`.
3392
+ */
3393
+ getKeyOperations() {
3394
+ if (this.#keyOperations) {
3395
+ return this.#keyOperations;
3396
+ }
3397
+ if (!this.#lazyLocalKeyOperations) {
3398
+ let cached;
3399
+ const resolve = async () => {
3400
+ const key = await this.getPrivateKey();
3401
+ if (!cached || cached.key !== key) {
3402
+ cached = { key, ops: (0, import_node_opcua_crypto8.keyOperationsFromPrivateKey)(key) };
3403
+ }
3404
+ return cached.ops;
3405
+ };
3406
+ this.#lazyLocalKeyOperations = {
3407
+ sign: async (data, params) => (await resolve()).sign(data, params),
3408
+ decryptBlock: async (block, params) => (await resolve()).decryptBlock(block, params),
3409
+ getKeyMetadata: async () => (await resolve()).getKeyMetadata(),
3410
+ getPublicKey: async () => (await resolve()).getPublicKey()
3411
+ };
3412
+ }
3413
+ return this.#lazyLocalKeyOperations;
3414
+ }
3415
+ /**
3416
+ * Fail closed at `initialize()` time, not on the first certificate
3417
+ * operation, if the key cannot actually be used: wrong/missing
3418
+ * passphrase on an encrypted key, a broken `privateKeyProvider`, or an
3419
+ * unreachable `keyOperations` provider (probed via `getKeyMetadata`).
3420
+ */
3421
+ async #probePrivateKey() {
3422
+ if (this.#keyOperations) {
3423
+ await this.#keyOperations.getKeyMetadata();
3424
+ return;
3425
+ }
3426
+ await this.getPrivateKey();
3427
+ }
3428
+ /**
3429
+ * The key to hand to a certificate-issuance primitive: the raw
3430
+ * {@link PrivateKey} for a local configuration, or a {@link CaSigner}
3431
+ * adapted from `keyOperations` when the key is opaque — which requires
3432
+ * the provider to implement `getPublicKey` (the adapter says so if not).
3433
+ */
3434
+ async #resolveSigningKey() {
3435
+ if (this.#keyOperations) {
3436
+ return (0, import_node_opcua_crypto8.caSignerFromKeyOperations)(this.#keyOperations);
3437
+ }
3438
+ return await this.getPrivateKey();
3439
+ }
3343
3440
  /**
3344
3441
  * Enable, disable, or rotate the passphrase protecting the on-disk
3345
3442
  * private key: decrypt with `oldPassphrase` (omit if the key is
@@ -3361,6 +3458,11 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3361
3458
  * disk file for this method to rewrite).
3362
3459
  */
3363
3460
  async reencryptPrivateKey(oldPassphrase, newPassphrase) {
3461
+ if (this.#keyOperations) {
3462
+ throw new import_node_opcua_crypto8.PrivateKeyUnavailableError(
3463
+ "reencryptPrivateKey: not supported when keyOperations is configured \u2014 there is no key material to rewrite"
3464
+ );
3465
+ }
3364
3466
  if (this.#privateKeyProvider) {
3365
3467
  throw new Error("reencryptPrivateKey: not supported when a privateKeyProvider is configured");
3366
3468
  }
@@ -3709,7 +3811,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3709
3811
  mkdirRecursiveSync(import_node_path8.default.join(pkiDir, "issuers"));
3710
3812
  mkdirRecursiveSync(import_node_path8.default.join(pkiDir, "issuers/certs"));
3711
3813
  mkdirRecursiveSync(import_node_path8.default.join(pkiDir, "issuers/crl"));
3712
- const ownsDiskKey = !this.#privateKeyProvider;
3814
+ const ownsDiskKey = !this.#privateKeyProvider && !this.#keyOperations;
3713
3815
  const needsKeyGeneration = ownsDiskKey && !import_node_fs11.default.existsSync(this.privateKey);
3714
3816
  const needsKeyEncryption = ownsDiskKey && !needsKeyGeneration && this.#privateKeyPassphrase !== void 0 && !isEncryptedPrivateKeyFile(this.privateKey);
3715
3817
  if (!import_node_fs11.default.existsSync(this.configFile) || needsKeyGeneration || needsKeyEncryption) {
@@ -3735,14 +3837,14 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3735
3837
  if (ownsDiskKey) {
3736
3838
  restrictPrivateFilePermissions(this.privateKey, 384);
3737
3839
  }
3738
- await this.getPrivateKey();
3840
+ await this.#probePrivateKey();
3739
3841
  await this.#readCertificates();
3740
3842
  });
3741
3843
  } else {
3742
3844
  if (ownsDiskKey) {
3743
3845
  restrictPrivateFilePermissions(this.privateKey, 384);
3744
3846
  }
3745
- await this.getPrivateKey();
3847
+ await this.#probePrivateKey();
3746
3848
  await this.#readCertificates();
3747
3849
  }
3748
3850
  }
@@ -3827,7 +3929,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3827
3929
  if (typeof params.applicationUri !== "string") {
3828
3930
  throw new Error("createSelfSignedCertificate: expecting applicationUri to be a string");
3829
3931
  }
3830
- if (!this.#privateKeyProvider && !import_node_fs11.default.existsSync(this.privateKey)) {
3932
+ if (!this.#privateKeyProvider && !this.#keyOperations && !import_node_fs11.default.existsSync(this.privateKey)) {
3831
3933
  throw new Error(`Cannot find private key ${this.privateKey}`);
3832
3934
  }
3833
3935
  let certificateFilename = import_node_path8.default.join(this.rootDir, "own/certs/self_signed_certificate.pem");
@@ -3836,7 +3938,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3836
3938
  ...params,
3837
3939
  rootDir: this.rootDir,
3838
3940
  configFile: this.configFile,
3839
- privateKey: await this.getPrivateKey(),
3941
+ privateKey: await this.#resolveSigningKey(),
3840
3942
  subject: params.subject || "CN=FIXME"
3841
3943
  };
3842
3944
  await this.withLock2(async () => {
@@ -3864,7 +3966,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
3864
3966
  ...params,
3865
3967
  rootDir: import_node_path8.default.resolve(this.rootDir),
3866
3968
  configFile: import_node_path8.default.resolve(this.configFile),
3867
- privateKey: await this.getPrivateKey()
3969
+ privateKey: await this.#resolveSigningKey()
3868
3970
  };
3869
3971
  return await this.withLock2(async () => {
3870
3972
  const now = /* @__PURE__ */ new Date();
@@ -4840,6 +4942,7 @@ async function dumpPFX(pfxFile, passphrase = "") {
4840
4942
  NativeCaBackend,
4841
4943
  OpenSslCaBackend,
4842
4944
  PrivateKeyPassphraseRequiredError,
4945
+ PrivateKeyUnavailableError,
4843
4946
  Subject,
4844
4947
  VerificationStatus,
4845
4948
  adjustApplicationUri,
@@ -4856,6 +4959,7 @@ async function dumpPFX(pfxFile, passphrase = "") {
4856
4959
  install_prerequisite,
4857
4960
  isIntermediateIssuer,
4858
4961
  isIssuer,
4962
+ isOpaqueSigner,
4859
4963
  isRootIssuer,
4860
4964
  makeFingerprint,
4861
4965
  quote,