node-opcua-pki 6.2.0 → 6.4.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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/index.ts","../lib/ca/certificate_authority.ts","../lib/toolbox/common.ts","../lib/toolbox/common2.ts","../lib/toolbox/config.ts","../lib/toolbox/debug.ts","../lib/toolbox/display.ts","../lib/toolbox/with_openssl/index.ts","../lib/toolbox/with_openssl/_env.ts","../lib/toolbox/with_openssl/create_certificate_signing_request.ts","../lib/misc/subject.ts","../lib/toolbox/with_openssl/execute_openssl.ts","../lib/toolbox/with_openssl/install_prerequisite.ts","../lib/toolbox/with_openssl/toolbox.ts","../lib/ca/templates/ca_config_template.cnf.ts","../lib/ca/crypto_create_CA.ts","../lib/misc/applicationurn.ts","../lib/misc/hostname.ts","../lib/pki/certificate_manager.ts","../lib/toolbox/without_openssl/create_certificate_signing_request.ts","../lib/toolbox/without_openssl/create_self_signed_certificate.ts","../lib/pki/templates/simple_config_template.cnf.ts"],"sourcesContent":["// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport { CertificateAuthority, type CertificateAuthorityOptions } from \"./ca/certificate_authority\";\nexport { main as pki_main } from \"./ca/crypto_create_CA\";\nexport * from \"./misc/subject\";\nexport * from \"./pki/certificate_manager\";\nexport * from \"./toolbox/index\";\nexport { install_prerequisite } from \"./toolbox/with_openssl/install_prerequisite\";\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-shadowed-variable\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n exploreCertificateSigningRequest,\n generatePrivateKeyFile,\n readCertificateSigningRequest,\n Subject,\n type SubjectOptions\n} from \"node-opcua-crypto\";\n\nimport {\n adjustApplicationUri,\n adjustDate,\n certificateFileExist,\n debugLog,\n displaySubtitle,\n displayTitle,\n type Filename,\n type KeySize,\n makePath,\n mkdirRecursiveSync,\n type Params,\n type ProcessAltNamesParam,\n quote\n} from \"../toolbox\";\n\nimport {\n type ExecuteOpenSSLOptions,\n type ExecuteOptions,\n ensure_openssl_installed,\n execute_openssl,\n execute_openssl_no_failure,\n generateStaticConfig,\n processAltNames,\n setEnv,\n x509Date\n} from \"../toolbox/with_openssl\";\n\nexport const defaultSubject = \"/C=FR/ST=IDF/L=Paris/O=Local NODE-OPCUA Certificate Authority/CN=NodeOPCUA-CA\";\n\nimport _ca_config_template from \"./templates/ca_config_template.cnf\";\n\n// tslint:disable-next-line:variable-name\nexport const configurationFileTemplate: string = _ca_config_template;\n\nconst config = {\n certificateDir: \"INVALID\",\n forceCA: false,\n pkiDir: \"INVALID\"\n};\n\nconst n = makePath;\nconst q = quote;\n\n// convert 'c07b9179' to \"192.123.145.121\"\nfunction octetStringToIpAddress(a: string) {\n return (\n parseInt(a.substring(0, 2), 16).toString() +\n \".\" +\n parseInt(a.substring(2, 4), 16).toString() +\n \".\" +\n parseInt(a.substring(4, 6), 16).toString() +\n \".\" +\n parseInt(a.substring(6, 8), 16).toString()\n );\n}\nassert(octetStringToIpAddress(\"c07b9179\") === \"192.123.145.121\");\nasync function construct_CertificateAuthority(certificateAuthority: CertificateAuthority): Promise<void> {\n // create the CA directory store\n // create the CA directory store\n //\n // PKI/CA\n // |\n // +-+> private\n // |\n // +-+> public\n // |\n // +-+> certs\n // |\n // +-+> crl\n // |\n // +-+> conf\n // |\n // +-f: serial\n // +-f: crlNumber\n // +-f: index.txt\n //\n\n const subject = certificateAuthority.subject;\n\n const caRootDir = path.resolve(certificateAuthority.rootDir);\n\n async function make_folders() {\n mkdirRecursiveSync(caRootDir);\n mkdirRecursiveSync(path.join(caRootDir, \"private\"));\n mkdirRecursiveSync(path.join(caRootDir, \"public\"));\n // xx execute(\"chmod 700 private\");\n mkdirRecursiveSync(path.join(caRootDir, \"certs\"));\n mkdirRecursiveSync(path.join(caRootDir, \"crl\"));\n mkdirRecursiveSync(path.join(caRootDir, \"conf\"));\n }\n await make_folders();\n\n async function construct_default_files() {\n const serial = path.join(caRootDir, \"serial\");\n if (!fs.existsSync(serial)) {\n await fs.promises.writeFile(serial, \"1000\");\n }\n\n const crlNumber = path.join(caRootDir, \"crlnumber\");\n if (!fs.existsSync(crlNumber)) {\n await fs.promises.writeFile(crlNumber, \"1000\");\n }\n\n const indexFile = path.join(caRootDir, \"index.txt\");\n if (!fs.existsSync(indexFile)) {\n await fs.promises.writeFile(indexFile, \"\");\n }\n }\n\n await construct_default_files();\n\n if (fs.existsSync(path.join(caRootDir, \"private/cakey.pem\")) && !config.forceCA) {\n // certificate already exists => do not overwrite\n debugLog(\"CA private key already exists ... skipping\");\n return;\n }\n\n // tslint:disable:no-empty\n displayTitle(\"Create Certificate Authority (CA)\");\n\n const indexFileAttr = path.join(caRootDir, \"index.txt.attr\");\n if (!fs.existsSync(indexFileAttr)) {\n await fs.promises.writeFile(indexFileAttr, \"unique_subject = no\");\n }\n\n const caConfigFile = certificateAuthority.configFile;\n if (1 || !fs.existsSync(caConfigFile)) {\n let data = configurationFileTemplate; // inlineText(configurationFile);\n data = makePath(data.replace(/%%ROOT_FOLDER%%/, caRootDir));\n\n await fs.promises.writeFile(caConfigFile, data);\n }\n\n // http://www.akadia.com/services/ssh_test_certificate.html\n const subjectOpt = ` -subj \"${subject.toString()}\" `;\n processAltNames({} as Params);\n\n const options = { cwd: caRootDir };\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", options);\n const configOption = ` -config ${q(n(configFile))}`;\n\n const keySize = certificateAuthority.keySize;\n\n const privateKeyFilename = path.join(caRootDir, \"private/cakey.pem\");\n const csrFilename = path.join(caRootDir, \"private/cakey.csr\");\n\n displayTitle(`Generate the CA private Key - ${keySize}`);\n // The first step is to create your RSA Private Key.\n // This key is a 1025,2048,3072 or 2038 bit RSA key which is encrypted using\n // Triple-DES and stored in a PEM format so that it is readable as ASCII text.\n await generatePrivateKeyFile(privateKeyFilename, keySize);\n displayTitle(\"Generate a certificate request for the CA key\");\n // Once the private key is generated a Certificate Signing Request can be generated.\n // The CSR is then used in one of two ways. Ideally, the CSR will be sent to a Certificate Authority, such as\n // Thawte or Verisign who will verify the identity of the requestor and issue a signed certificate.\n // The second option is to self-sign the CSR, which will be demonstrated in the next section\n await execute_openssl(\n \"req -new\" +\n \" -sha256 \" +\n \" -text \" +\n \" -extensions v3_ca\" +\n configOption +\n \" -key \" +\n q(n(privateKeyFilename)) +\n \" -out \" +\n q(n(csrFilename)) +\n \" \" +\n subjectOpt,\n options\n );\n\n // xx // Step 3: Remove Passphrase from Key\n // xx execute(\"cp private/cakey.pem private/cakey.pem.org\");\n // xx execute(openssl_path + \" rsa -in private/cakey.pem.org -out private/cakey.pem -passin pass:\"+paraphrase);\n\n displayTitle(\"Generate CA Certificate (self-signed)\");\n await execute_openssl(\n \" x509 -sha256 -req -days 3650 \" +\n \" -text \" +\n \" -extensions v3_ca\" +\n \" -extfile \" +\n q(n(configFile)) +\n \" -in private/cakey.csr \" +\n \" -signkey \" +\n q(n(privateKeyFilename)) +\n \" -out public/cacert.pem\",\n options\n );\n displaySubtitle(\"generate initial CRL (Certificate Revocation List)\");\n await regenerateCrl(certificateAuthority.revocationList, configOption, options);\n displayTitle(\"Create Certificate Authority (CA) ---> DONE\");\n}\n\nasync function regenerateCrl(revocationList: string, configOption: string, options: ExecuteOpenSSLOptions) {\n // produce a CRL in PEM format\n displaySubtitle(\"regenerate CRL (Certificate Revocation List)\");\n await execute_openssl(`ca -gencrl ${configOption} -out crl/revocation_list.crl`, options);\n await execute_openssl(\"crl \" + \" -in crl/revocation_list.crl -out crl/revocation_list.der \" + \" -outform der\", options);\n\n displaySubtitle(\"Display (Certificate Revocation List)\");\n await execute_openssl(`crl -in ${q(n(revocationList))} -text -noout`, options);\n}\n\nexport interface CertificateAuthorityOptions {\n keySize: KeySize;\n location: string;\n subject?: string | SubjectOptions;\n}\n\nexport class CertificateAuthority {\n public readonly keySize: KeySize;\n public readonly location: string;\n public readonly subject: Subject;\n\n constructor(options: CertificateAuthorityOptions) {\n assert(Object.prototype.hasOwnProperty.call(options, \"location\"));\n assert(Object.prototype.hasOwnProperty.call(options, \"keySize\"));\n this.location = options.location;\n this.keySize = options.keySize || 2048;\n this.subject = new Subject(options.subject || defaultSubject);\n }\n\n public get rootDir() {\n return this.location;\n }\n\n public get configFile() {\n return path.normalize(path.join(this.rootDir, \"./conf/caconfig.cnf\"));\n }\n\n public get caCertificate() {\n // the Certificate Authority Certificate\n return makePath(this.rootDir, \"./public/cacert.pem\");\n }\n\n /**\n * the file name where the current Certificate Revocation List is stored (in DER format)\n */\n public get revocationListDER() {\n return makePath(this.rootDir, \"./crl/revocation_list.der\");\n }\n\n /**\n * the file name where the current Certificate Revocation List is stored (in PEM format)\n */\n public get revocationList() {\n return makePath(this.rootDir, \"./crl/revocation_list.crl\");\n }\n\n public get caCertificateWithCrl() {\n return makePath(this.rootDir, \"./public/cacertificate_with_crl.pem\");\n }\n\n public async initialize(): Promise<void> {\n await construct_CertificateAuthority(this);\n }\n\n public async constructCACertificateWithCRL(): Promise<void> {\n const cacertWithCRL = this.caCertificateWithCrl;\n\n // note : in order to check if the certificate is revoked,\n // you need to specify -crl_check and have both the CA cert and the (applicable) CRL in your trust store.\n // There are two ways to do that:\n // 1. concatenate cacert.pem and crl.pem into one file and use that for -CAfile.\n // 2. use some linked\n // ( from http://security.stackexchange.com/a/58305/59982)\n\n if (fs.existsSync(this.revocationList)) {\n await fs.promises.writeFile(\n cacertWithCRL,\n fs.readFileSync(this.caCertificate, \"utf8\") + fs.readFileSync(this.revocationList, \"utf8\")\n );\n } else {\n // there is no revocation list yet\n await fs.promises.writeFile(cacertWithCRL, fs.readFileSync(this.caCertificate));\n }\n }\n\n public async constructCertificateChain(certificate: Filename): Promise<void> {\n assert(fs.existsSync(certificate));\n assert(fs.existsSync(this.caCertificate));\n\n debugLog(chalk.yellow(\" certificate file :\"), chalk.cyan(certificate));\n // append\n await fs.promises.writeFile(\n certificate,\n (await fs.promises.readFile(certificate, \"utf8\")) + (await fs.promises.readFile(this.caCertificate, \"utf8\"))\n // + fs.readFileSync(this.revocationList)\n );\n }\n\n public async createSelfSignedCertificate(certificateFile: Filename, privateKey: Filename, params: Params): Promise<void> {\n assert(typeof privateKey === \"string\");\n assert(fs.existsSync(privateKey));\n\n if (!certificateFileExist(certificateFile)) {\n return;\n }\n\n adjustDate(params);\n adjustApplicationUri(params);\n processAltNames(params);\n\n const csrFile = `${certificateFile}_csr`;\n assert(csrFile);\n const configFile = generateStaticConfig(this.configFile, { cwd: this.rootDir });\n\n const options = {\n cwd: this.rootDir,\n openssl_conf: makePath(configFile)\n };\n\n const configOption = \"\";\n\n const subject = params.subject ? new Subject(params.subject).toString() : \"\";\n const subjectOptions = subject && subject.length > 1 ? ` -subj ${subject} ` : \"\";\n\n displaySubtitle(\"- the certificate signing request\");\n await execute_openssl(\n \"req \" +\n \" -new -sha256 -text \" +\n configOption +\n subjectOptions +\n \" -batch -key \" +\n q(n(privateKey)) +\n \" -out \" +\n q(n(csrFile)),\n options\n );\n\n displaySubtitle(\"- creating the self-signed certificate\");\n await execute_openssl(\n \"ca \" +\n \" -selfsign \" +\n \" -keyfile \" +\n q(n(privateKey)) +\n \" -startdate \" +\n x509Date(params.startDate) +\n \" -enddate \" +\n x509Date(params.endDate) +\n \" -batch -out \" +\n q(n(certificateFile)) +\n \" -in \" +\n q(n(csrFile)),\n options\n );\n\n displaySubtitle(\"- dump the certificate for a check\");\n\n await execute_openssl(`x509 -in ${q(n(certificateFile))} -dates -fingerprint -purpose -noout`, {});\n\n displaySubtitle(\"- verify self-signed certificate\");\n await execute_openssl_no_failure(`verify -verbose -CAfile ${q(n(certificateFile))} ${q(n(certificateFile))}`, options);\n\n await fs.promises.unlink(csrFile);\n }\n\n /**\n * revoke a certificate and update the CRL\n *\n * @method revokeCertificate\n * @param certificate - the certificate to revoke\n * @param params\n * @param [params.reason = \"keyCompromise\" {String}]\n * @async\n */\n public async revokeCertificate(certificate: Filename, params: Params): Promise<void> {\n const crlReasons = [\n \"unspecified\",\n \"keyCompromise\",\n \"CACompromise\",\n \"affiliationChanged\",\n \"superseded\",\n \"cessationOfOperation\",\n \"certificateHold\",\n \"removeFromCRL\"\n ];\n\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", { cwd: this.rootDir });\n\n const options = {\n cwd: this.rootDir,\n openssl_conf: makePath(configFile)\n };\n\n setEnv(\"ALTNAME\", \"\");\n const randomFile = path.join(this.rootDir, \"random.rnd\");\n setEnv(\"RANDFILE\", randomFile);\n\n // // tslint:disable-next-line:no-string-literal\n // if (!fs.existsSync((process.env as any)[\"OPENSSL_CONF\"])) {\n // throw new Error(\"Cannot find OPENSSL_CONF\");\n // }\n\n const configOption = ` -config ${q(n(configFile))}`;\n\n const reason = params.reason || \"keyCompromise\";\n assert(crlReasons.indexOf(reason) >= 0);\n\n displayTitle(`Revoking certificate ${certificate}`);\n\n displaySubtitle(\"Revoke certificate\");\n\n await execute_openssl_no_failure(`ca -verbose ${configOption} -revoke ${q(certificate)} -crl_reason ${reason}`, options);\n // regenerate CRL (Certificate Revocation List)\n await regenerateCrl(this.revocationList, configOption, options);\n\n displaySubtitle(\"Verify that certificate is revoked\");\n\n await execute_openssl_no_failure(\n \"verify -verbose\" +\n // configOption +\n \" -CRLfile \" +\n q(n(this.revocationList)) +\n \" -CAfile \" +\n q(n(this.caCertificate)) +\n \" -crl_check \" +\n q(n(certificate)),\n options\n );\n\n // produce CRL in DER format\n displaySubtitle(\"Produce CRL in DER form \");\n await execute_openssl(`crl -in ${q(n(this.revocationList))} -out crl/revocation_list.der -outform der`, options);\n // produce CRL in PEM format with text\n displaySubtitle(\"Produce CRL in PEM form \");\n\n await execute_openssl(`crl -in ${q(n(this.revocationList))} -out crl/revocation_list.pem -outform pem -text `, options);\n }\n\n /**\n *\n * @param certificate - the certificate filename to generate\n * @param certificateSigningRequestFilename - the certificate signing request\n * @param params - parameters\n * @param params.applicationUri - the applicationUri\n * @param params.startDate - startDate of the certificate\n * @param params.validity - number of day of validity of the certificate\n */\n public async signCertificateRequest(\n certificate: Filename,\n certificateSigningRequestFilename: Filename,\n params1: Params\n ): Promise<Filename> {\n await ensure_openssl_installed();\n assert(fs.existsSync(certificateSigningRequestFilename));\n if (!certificateFileExist(certificate)) {\n return \"\";\n }\n adjustDate(params1);\n adjustApplicationUri(params1);\n processAltNames(params1);\n\n const options: ExecuteOptions = { cwd: this.rootDir };\n\n // note :\n // subjectAltName is not copied across\n // see https://github.com/openssl/openssl/issues/10458\n const csr = await readCertificateSigningRequest(certificateSigningRequestFilename);\n const csrInfo = exploreCertificateSigningRequest(csr);\n\n const applicationUri = csrInfo.extensionRequest.subjectAltName.uniformResourceIdentifier\n ? csrInfo.extensionRequest.subjectAltName.uniformResourceIdentifier[0]\n : undefined;\n if (typeof applicationUri !== \"string\") {\n throw new Error(\"Cannot find applicationUri in CSR\");\n }\n\n const dns = csrInfo.extensionRequest.subjectAltName.dNSName || [];\n let ip = csrInfo.extensionRequest.subjectAltName.iPAddress || [];\n ip = ip.map(octetStringToIpAddress);\n\n const params: ProcessAltNamesParam = {\n applicationUri,\n dns,\n ip\n };\n\n processAltNames(params);\n\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", options);\n\n displaySubtitle(\"- then we ask the authority to sign the certificate signing request\");\n\n const configOption = ` -config ${configFile}`;\n await execute_openssl(\n \"ca \" +\n configOption +\n \" -startdate \" +\n x509Date(params1.startDate) +\n \" -enddate \" +\n x509Date(params1.endDate) +\n \" -batch -out \" +\n q(n(certificate)) +\n \" -in \" +\n q(n(certificateSigningRequestFilename)),\n options\n );\n\n displaySubtitle(\"- dump the certificate for a check\");\n await execute_openssl(`x509 -in ${q(n(certificate))} -dates -fingerprint -purpose -noout`, options);\n\n displaySubtitle(\"- construct CA certificate with CRL\");\n await this.constructCACertificateWithCRL();\n\n // construct certificate chain\n // concatenate certificate with CA Certificate and revocation list\n displaySubtitle(\"- construct certificate chain\");\n await this.constructCertificateChain(certificate);\n // todo\n displaySubtitle(\"- verify certificate against the root CA\");\n await this.verifyCertificate(certificate);\n\n return certificate;\n }\n\n public async verifyCertificate(certificate: Filename): Promise<void> {\n // openssl verify crashes on windows! we cannot use it reliably\n // istanbul ignore next\n const isImplemented = false;\n\n // istanbul ignore next\n if (isImplemented) {\n const options = { cwd: this.rootDir };\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", options);\n\n setEnv(\"OPENSSL_CONF\", makePath(configFile));\n const _configOption = ` -config ${configFile}`;\n _configOption;\n await execute_openssl_no_failure(\n `verify -verbose -CAfile ${q(n(this.caCertificateWithCrl))} ${q(n(certificate))}`,\n options\n );\n }\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\n\nexport type KeySize = 1024 | 2048 | 3072 | 4096;\nexport type Thumbprint = string;\nexport type Filename = string;\nexport type CertificateStatus = \"unknown\" | \"trusted\" | \"rejected\";\n\nimport type { CertificatePurpose } from \"node-opcua-crypto\";\nimport type { SubjectOptions } from \"../misc/subject\";\n\nexport type KeyLength = 1024 | 2048 | 3072 | 4096;\n\nexport function quote(str?: string): string {\n return `\"${str || \"\"}\"`;\n}\n\nexport interface ProcessAltNamesParam {\n dns?: string[];\n ip?: string[];\n applicationUri?: string;\n}\n\n// tslint:disable-next:no-empty-interface\nexport interface CreateCertificateSigningRequestOptions extends ProcessAltNamesParam {\n subject?: SubjectOptions | string;\n}\n\nexport interface CreateCertificateSigningRequestWithConfigOptions extends CreateCertificateSigningRequestOptions {\n rootDir: Filename;\n configFile: Filename;\n privateKey: Filename;\n purpose: CertificatePurpose;\n}\n\nexport interface StartDateEndDateParam {\n startDate?: Date;\n endDate?: Date;\n validity?: number;\n}\n\nexport interface CreateSelfSignCertificateParam extends ProcessAltNamesParam, StartDateEndDateParam {\n subject?: SubjectOptions | string;\n}\n\n// purpose of self-signed certificate\n\nexport interface CreateSelfSignCertificateWithConfigParam extends CreateSelfSignCertificateParam {\n rootDir: Filename;\n configFile: Filename;\n privateKey: Filename;\n purpose: CertificatePurpose;\n}\n\nexport interface Params extends ProcessAltNamesParam, StartDateEndDateParam {\n subject?: SubjectOptions | string;\n\n privateKey?: string;\n configFile?: string;\n rootDir?: string;\n\n outputFile?: string;\n reason?: string;\n}\n\nexport function adjustDate(params: StartDateEndDateParam) {\n assert(params instanceof Object);\n params.startDate = params.startDate || new Date();\n assert(params.startDate instanceof Date);\n\n params.validity = params.validity || 365; // one year\n\n params.endDate = new Date(params.startDate.getTime());\n params.endDate.setDate(params.startDate.getDate() + params.validity);\n\n // params.endDate = x509Date(endDate);\n // params.startDate = x509Date(startDate);\n\n assert(params.endDate instanceof Date);\n assert(params.startDate instanceof Date);\n\n // // istanbul ignore next\n // if (!g_config.silent) {\n // warningLog(\" start Date \", params.startDate.toUTCString(), x509Date(params.startDate));\n // warningLog(\" end Date \", params.endDate.toUTCString(), x509Date(params.endDate));\n // }\n}\n\nexport function adjustApplicationUri(params: Params) {\n const applicationUri = params.applicationUri || \"\";\n if (applicationUri.length > 200) {\n throw new Error(`Openssl doesn't support urn with length greater than 200${applicationUri}`);\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport chalk from \"chalk\";\n\nimport { g_config } from \"./config\";\n\nimport { debugLog, warningLog } from \"./debug\";\n\nexport function certificateFileExist(certificateFile: string): boolean {\n // istanbul ignore next\n if (fs.existsSync(certificateFile) && !g_config.force) {\n warningLog(\n chalk.yellow(\" certificate \") + chalk.cyan(certificateFile) + chalk.yellow(\" already exists => do not overwrite\")\n );\n return false;\n }\n return true;\n}\n\nexport function mkdirRecursiveSync(folder: string): void {\n if (!fs.existsSync(folder)) {\n // istanbul ignore next\n debugLog(chalk.white(\" .. constructing \"), folder);\n fs.mkdirSync(folder, { recursive: true });\n }\n}\n\nexport function makePath(folderName: string, filename?: string): string {\n let s: string;\n if (filename) {\n s = path.join(path.normalize(folderName), filename);\n } else {\n assert(folderName);\n s = folderName;\n }\n s = s.replace(/\\\\/g, \"/\");\n return s;\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nexport const g_config = {\n opensslVersion: \"unset\",\n silent: process.env.VERBOSE ? !process.env.VERBOSE : true,\n force: false\n};\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nexport const doDebug = process.env.NODEOPCUAPKIDEBUG || false;\nexport const displayError = true;\nexport const displayDebug = !!process.env.NODEOPCUAPKIDEBUG || false;\n// tslint:disable-next-line:no-empty\nexport function debugLog(...args: unknown[]) {\n // istanbul ignore next\n if (displayDebug) {\n console.log.apply(null, args);\n }\n}\nexport function warningLog(...args: unknown[]) {\n console.log.apply(null, args);\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport chalk from \"chalk\";\nimport { g_config } from \"./config\";\nimport { warningLog } from \"./debug\";\n\n// istanbul ignore next\nexport function displayChapter(str: string) {\n const l = \" \";\n warningLog(`${chalk.bgWhite(l)} `);\n str = ` ${str}${l}`.substring(0, l.length);\n warningLog(chalk.bgWhite.cyan(str));\n warningLog(`${chalk.bgWhite(l)} `);\n}\n\nexport function displayTitle(str: string) {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(\"\");\n warningLog(chalk.yellowBright(str));\n warningLog(chalk.yellow(new Array(str.length + 1).join(\"=\")), \"\\n\");\n }\n}\n\nexport function displaySubtitle(str: string) {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(\"\");\n warningLog(` ${chalk.yellowBright(str)}`);\n warningLog(` ${chalk.white(new Array(str.length + 1).join(\"-\"))}`, \"\\n\");\n }\n}\nexport function display(str: string) {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(` ${str}`);\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport exp from \"node:constants\";\n\nconst _exp = exp;\n\nexport * from \"./_env\";\nexport * from \"./create_certificate_signing_request\";\nexport * from \"./execute_openssl\";\nexport * from \"./install_prerequisite\";\nexport * from \"./toolbox\";\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport type { ProcessAltNamesParam } from \"../common\";\nimport { g_config } from \"../config\";\nimport { warningLog } from \"../debug\";\n\nexport const exportedEnvVars: Record<string, string> = {};\n\nexport function setEnv(varName: string, value: string): void {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(` set ${varName}=${value}`);\n }\n exportedEnvVars[varName] = value;\n\n if ([\"OPENSSL_CONF\"].indexOf(varName) >= 0) {\n process.env[varName] = value;\n }\n if ([\"RANDFILE\"].indexOf(varName) >= 0) {\n process.env[varName] = value;\n }\n}\n\nexport function hasEnv(varName: string): boolean {\n return Object.prototype.hasOwnProperty.call(exportedEnvVars, varName);\n}\nexport function getEnv(varName: string): string {\n return exportedEnvVars[varName];\n}\n\nexport function getEnvironmentVarNames(): { key: string; pattern: string }[] {\n return Object.keys(exportedEnvVars).map((varName: string) => {\n return { key: varName, pattern: `\\\\$ENV\\\\:\\\\:${varName}` };\n });\n}\n\nexport function processAltNames(params: ProcessAltNamesParam) {\n params.dns = params.dns || [];\n params.ip = params.ip || [];\n\n // construct subjectAtlName\n let subjectAltName: string[] = [];\n subjectAltName.push(`URI:${params.applicationUri}`);\n subjectAltName = ([] as string[]).concat(\n subjectAltName,\n params.dns.map((d: string) => `DNS:${d}`)\n );\n subjectAltName = ([] as string[]).concat(\n subjectAltName,\n params.ip.map((d: string) => `IP:${d}`)\n );\n const subjectAltNameString = subjectAltName.join(\", \");\n setEnv(\"ALTNAME\", subjectAltNameString);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { Subject } from \"../../misc/subject\";\nimport { type CreateCertificateSigningRequestWithConfigOptions, quote } from \"../common\";\nimport { makePath } from \"../common2\";\nimport { displaySubtitle } from \"../display\";\nimport { processAltNames } from \"./_env\";\nimport { execute_openssl } from \"./execute_openssl\";\nimport { generateStaticConfig } from \"./toolbox\";\n\nconst q = quote;\nconst n = makePath;\n\n/**\n * create a certificate signing request\n */\nexport async function createCertificateSigningRequestWithOpenSSL(\n certificateSigningRequestFilename: string,\n params: CreateCertificateSigningRequestWithConfigOptions\n): Promise<void> {\n assert(params);\n assert(params.rootDir);\n assert(params.configFile);\n assert(params.privateKey);\n assert(typeof params.privateKey === \"string\");\n assert(fs.existsSync(params.configFile), `config file must exist ${params.configFile}`);\n assert(fs.existsSync(params.privateKey), `Private key must exist${params.privateKey}`);\n assert(fs.existsSync(params.rootDir), \"RootDir key must exist\");\n assert(typeof certificateSigningRequestFilename === \"string\");\n\n // note : this openssl command requires a config file\n processAltNames(params);\n const configFile = generateStaticConfig(params.configFile, { cwd: params.rootDir });\n\n const options = { cwd: params.rootDir, openssl_conf: path.relative(params.rootDir, configFile) };\n\n const configOption = ` -config ${q(n(configFile))}`;\n\n const subject = params.subject ? new Subject(params.subject).toString() : undefined;\n // process.env.OPENSSL_CONF =\"\";\n const subjectOptions = subject ? ` -subj \"${subject}\"` : \"\";\n\n displaySubtitle(\"- Creating a Certificate Signing Request with openssl\");\n await execute_openssl(\n \"req -new\" +\n \" -sha256 \" +\n \" -batch \" +\n \" -text \" +\n configOption +\n \" -key \" +\n q(n(params.privateKey)) +\n subjectOptions +\n \" -out \" +\n q(n(certificateSigningRequestFilename)),\n options\n );\n}\n","export type { SubjectOptions } from \"node-opcua-crypto\";\nexport { Subject } from \"node-opcua-crypto\";\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\nimport child_process from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport byline from \"byline\";\nimport chalk from \"chalk\";\nimport { quote } from \"../common\";\nimport { makePath } from \"../common2\";\nimport { g_config } from \"../config\";\nimport { debugLog, displayError, doDebug, warningLog } from \"../debug\";\nimport { setEnv } from \"./_env\";\nimport { get_openssl_exec_path } from \"./install_prerequisite\";\n\n// tslint:disable-next-line:variable-name\n\nlet opensslPath: string | undefined; // not initialized\n\nconst n = makePath;\n\nexport interface ExecuteOptions {\n cwd?: string;\n hideErrorMessage?: boolean;\n}\n\nexport async function execute(cmd: string, options: ExecuteOptions): Promise<string> {\n const from = new Error();\n\n options.cwd = options.cwd || process.cwd();\n\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(chalk.cyan(\" CWD \"), options.cwd);\n }\n\n const outputs: string[] = [];\n\n return await new Promise((resolve, reject) => {\n const child = child_process.exec(\n cmd,\n {\n cwd: options.cwd,\n windowsHide: true\n },\n (err: child_process.ExecException | null) => {\n // istanbul ignore next\n if (err) {\n if (!options.hideErrorMessage) {\n const fence = \"###########################################\";\n console.error(chalk.bgWhiteBright.redBright(`${fence} OPENSSL ERROR ${fence}`));\n console.error(chalk.bgWhiteBright.redBright(`CWD = ${options.cwd}`));\n console.error(chalk.bgWhiteBright.redBright(err.message));\n console.error(chalk.bgWhiteBright.redBright(`${fence} OPENSSL ERROR ${fence}`));\n\n console.error(from.stack);\n }\n reject(new Error(err.message));\n return;\n }\n resolve(outputs.join(\"\"));\n }\n );\n\n if (child.stdout) {\n const stream2 = byline(child.stdout);\n stream2.on(\"data\", (line: string) => {\n outputs.push(`${line}\\n`);\n });\n if (!g_config.silent) {\n stream2.on(\"data\", (line: string) => {\n line = line.toString();\n if (doDebug) {\n process.stdout.write(`${chalk.white(\" stdout \") + chalk.whiteBright(line)}\\n`);\n }\n });\n }\n }\n\n // istanbul ignore next\n if (!g_config.silent) {\n if (child.stderr) {\n const stream1 = byline(child.stderr);\n stream1.on(\"data\", (line: string) => {\n line = line.toString();\n if (displayError) {\n process.stdout.write(`${chalk.white(\" stderr \") + chalk.red(line)}\\n`);\n }\n });\n }\n }\n });\n}\n\nexport async function find_openssl(): Promise<string> {\n return await get_openssl_exec_path();\n}\n\nexport async function ensure_openssl_installed(): Promise<void> {\n if (!opensslPath) {\n opensslPath = await find_openssl();\n const outputs = await execute_openssl(\"version\", { cwd: \".\" });\n g_config.opensslVersion = outputs.trim();\n if (doDebug) {\n warningLog(\"OpenSSL version : \", g_config.opensslVersion);\n }\n }\n}\n\nexport async function executeOpensslAsync(cmd: string, options: ExecuteOpenSSLOptions): Promise<string> {\n return await execute_openssl(cmd, options);\n}\n\nexport async function execute_openssl_no_failure(cmd: string, options: ExecuteOpenSSLOptions) {\n options = options || {};\n options.hideErrorMessage = true;\n try {\n return await execute_openssl(cmd, options);\n } catch (err) {\n debugLog(\" (ignored error = ERROR : )\", (err as Error).message);\n }\n}\n\nfunction getTempFolder(): string {\n return os.tmpdir();\n}\n\nexport interface ExecuteOpenSSLOptions extends ExecuteOptions {\n openssl_conf?: string;\n}\n\nexport async function execute_openssl(cmd: string, options: ExecuteOpenSSLOptions): Promise<string> {\n debugLog(\"execute_openssl\", cmd, options);\n const empty_config_file = n(getTempFolder(), \"empty_config.cnf\");\n if (!fs.existsSync(empty_config_file)) {\n await fs.promises.writeFile(empty_config_file, \"# empty config file\");\n }\n\n options = options || {};\n options.openssl_conf = options.openssl_conf || empty_config_file; // \"!! OPEN SLL CONF NOT DEFINED BAD FILE !!\";\n assert(options.openssl_conf);\n setEnv(\"OPENSSL_CONF\", options.openssl_conf);\n\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(chalk.cyan(\" OPENSSL_CONF\"), process.env.OPENSSL_CONF);\n warningLog(chalk.cyan(\" RANDFILE \"), process.env.RANDFILE);\n warningLog(chalk.cyan(\" CMD openssl \"), chalk.cyanBright(cmd));\n }\n await ensure_openssl_installed();\n return await execute(`${quote(opensslPath)} ${cmd}`, options);\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport child_process from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { Readable } from \"node:stream\";\nimport url from \"node:url\";\n\nimport byline from \"byline\";\nimport chalk from \"chalk\";\nimport ProgressBar from \"progress\";\nimport wget from \"wget-improved-2\";\nimport yauzl from \"yauzl\";\n\nimport { warningLog } from \"../debug\";\n\nconst doDebug = process.env.NODEOPCUAPKIDEBUG || false;\n\ndeclare interface ProxyOptions {\n host: string;\n port: number;\n localAddress?: string;\n proxyAuth?: string;\n headers?: Record<string, string>;\n protocol: string; // \"https\" | \"http\"\n}\ndeclare interface WgetOptions {\n gunzip?: boolean;\n proxy?: ProxyOptions;\n}\n\ndeclare interface WgetInterface {\n download(url: string, outputFilename: string, options: WgetOptions): NodeJS.EventEmitter;\n}\n\ninterface ExecuteResult {\n exitCode: number;\n output: string;\n}\n\nfunction makeOptions(): WgetOptions {\n const proxy =\n process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || undefined;\n if (proxy) {\n const a = new url.URL(proxy);\n const auth = a.username ? `${a.username}:${a.password}` : undefined;\n\n const options: WgetOptions = {\n proxy: {\n port: a.port ? parseInt(a.port, 10) : 80,\n protocol: a.protocol.replace(\":\", \"\"),\n host: a.hostname ?? \"\",\n proxyAuth: auth\n }\n };\n warningLog(chalk.green(\"- using proxy \"), proxy);\n warningLog(options);\n return options;\n }\n return {};\n}\n\nasync function execute(cmd: string, cwd?: string): Promise<ExecuteResult> {\n let output = \"\";\n\n // xx cwd = cwd ? {cwd: cwd} : {};\n const options = {\n cwd,\n windowsHide: true\n };\n\n return await new Promise<ExecuteResult>((resolve, reject) => {\n const child = child_process.exec(\n cmd,\n options,\n (err: child_process.ExecException | null /*, stdout: string, stderr: string*/) => {\n const exitCode = err === null ? 0 : err.code || 1;\n if (err) reject(err);\n else {\n resolve({ exitCode, output });\n }\n }\n );\n\n const stream1 = byline(child.stdout as Readable);\n stream1.on(\"data\", (line: string) => {\n output += `${line}\\n`;\n // istanbul ignore next\n if (doDebug) {\n process.stdout.write(` stdout ${chalk.yellow(line)}\\n`);\n }\n });\n });\n}\n\nfunction quote(str: string): string {\n return `\"${str.replace(/\\\\/g, \"/\")}\"`;\n}\n\nfunction is_expected_openssl_version(strVersion: string): boolean {\n return !!strVersion.match(/OpenSSL 1|3/);\n}\n\nasync function getopensslExecPath(): Promise<string> {\n let result1: ExecuteResult | undefined;\n try {\n result1 = await execute(\"which openssl\");\n } catch (err) {\n warningLog(\"warning: \", (err as Error).message);\n throw new Error(\"Cannot find openssl\");\n }\n\n const exitCode = result1?.exitCode;\n const output = result1?.output;\n\n if (exitCode !== 0) {\n warningLog(chalk.yellow(\" it seems that \") + chalk.cyan(\"openssl\") + chalk.yellow(\" is not installed on your computer \"));\n warningLog(chalk.yellow(\"Please install it before running this programs\"));\n throw new Error(\"Cannot find openssl\");\n }\n const opensslExecPath = output.replace(/\\n\\r/g, \"\").trim();\n return opensslExecPath;\n}\nexport async function check_system_openssl_version(): Promise<string> {\n const opensslExecPath = await getopensslExecPath();\n\n // tslint:disable-next-line:variable-name\n const q_opensslExecPath = quote(opensslExecPath);\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(` OpenSSL found in : ${chalk.yellow(opensslExecPath)}`);\n }\n // ------------------------ now verify that openssl version is the correct one\n const result = await execute(`${q_opensslExecPath} version`);\n\n const exitCode = result?.exitCode;\n const output = result?.output;\n\n const version = output.trim();\n\n const versionOK = exitCode === 0 && is_expected_openssl_version(version);\n if (!versionOK) {\n let message =\n chalk.whiteBright(\"Warning !!!!!!!!!!!! \") +\n \"\\nyour version of openssl is \" +\n version +\n \". It doesn't match the expected version\";\n\n if (process.platform === \"darwin\") {\n message +=\n chalk.cyan(\"\\nplease refer to :\") +\n chalk.yellow(\" https://github.com/node-opcua/node-opcua/\" + \"wiki/installing-node-opcua-or-node-red-on-MacOS\");\n }\n\n console.log(message);\n }\n return output;\n}\n\nasync function install_and_check_win32_openssl_version(): Promise<string> {\n const downloadFolder = path.join(os.tmpdir(), \".\");\n\n function get_openssl_folder_win32(): string {\n if (process.env.LOCALAPPDATA) {\n const userProgramFolder = path.join(process.env.LOCALAPPDATA, \"Programs\");\n if (fs.existsSync(userProgramFolder)) {\n return path.join(userProgramFolder, \"openssl\");\n }\n }\n return path.join(process.cwd(), \"openssl\");\n }\n\n function get_openssl_exec_path_win32(): string {\n const opensslFolder = get_openssl_folder_win32();\n return path.join(opensslFolder, \"openssl.exe\");\n }\n\n async function check_openssl_win32(): Promise<{ opensslOk?: boolean; version?: string }> {\n const opensslExecPath = get_openssl_exec_path_win32();\n\n const exists = fs.existsSync(opensslExecPath);\n if (!exists) {\n warningLog(\"checking presence of \", opensslExecPath);\n warningLog(chalk.red(\" cannot find file \") + opensslExecPath);\n return {\n opensslOk: false,\n version: `cannot find file ${opensslExecPath}`\n };\n } else {\n // tslint:disable-next-line:variable-name\n const q_openssl_exe_path = quote(opensslExecPath);\n const cwd = \".\";\n\n const { exitCode, output } = await execute(`${q_openssl_exe_path} version`, cwd);\n const version = output.trim();\n // istanbul ignore next\n\n if (doDebug) {\n warningLog(\" Version = \", version);\n }\n return {\n opensslOk: exitCode === 0 && is_expected_openssl_version(version),\n version\n };\n }\n }\n\n /**\n * detect whether windows OS is a 64 bits or 32 bits\n * http://ss64.com/nt/syntax-64bit.html\n * http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx\n * @return {number}\n */\n function win32or64(): 32 | 64 {\n if (process.env.PROCESSOR_ARCHITECTURE === \"x86\" && process.env.PROCESSOR_ARCHITEW6432) {\n return 64;\n }\n\n if (process.env.PROCESSOR_ARCHITECTURE === \"AMD64\") {\n return 64;\n }\n\n // check if we are running node x32 on a x64 arch\n if (process.env.CURRENT_CPU === \"x64\") {\n return 64;\n }\n return 32;\n }\n\n async function download_openssl(): Promise<{ downloadedFile: string }> {\n // const url = (win32or64() === 64 )\n // ? \"http://indy.fulgan.com/SSL/openssl-1.0.2o-x64_86-win64.zip\"\n // : \"http://indy.fulgan.com/SSL/openssl-1.0.2o-i386-win32.zip\"\n // ;\n const url =\n win32or64() === 64\n ? \"https://github.com/node-opcua/node-opcua-pki/releases/download/2.14.2/openssl-1.0.2u-x64_86-win64.zip\"\n : \"https://github.com/node-opcua/node-opcua-pki/releases/download/2.14.2/openssl-1.0.2u-i386-win32.zip\";\n // the zip file\n const outputFilename = path.join(downloadFolder, path.basename(url));\n\n warningLog(`downloading ${chalk.yellow(url)} to ${outputFilename}`);\n\n if (fs.existsSync(outputFilename)) {\n return { downloadedFile: outputFilename };\n }\n const options = makeOptions();\n const bar = new ProgressBar(chalk.cyan(\"[:bar]\") + chalk.cyan(\" :percent \") + chalk.white(\":etas\"), {\n complete: \"=\",\n incomplete: \" \",\n total: 100,\n width: 100\n });\n\n return await new Promise((resolve, reject) => {\n const download = wget.download(url, outputFilename, options);\n download.on(\"error\", (err: Error) => {\n warningLog(err);\n setImmediate(() => {\n reject(err);\n });\n });\n download.on(\"end\", (output: string) => {\n // istanbul ignore next\n if (doDebug) {\n warningLog(output);\n }\n // warningLog(\"done ...\");\n resolve({ downloadedFile: outputFilename });\n });\n download.on(\"progress\", (progress: number) => {\n bar.update(progress);\n });\n });\n }\n\n async function unzip_openssl(zipFilename: string) {\n const opensslFolder = get_openssl_folder_win32();\n\n const zipFile = await new Promise<yauzl.ZipFile>((resolve, reject) => {\n yauzl.open(zipFilename, { lazyEntries: true }, (err?: Error | null, zipfile?: yauzl.ZipFile) => {\n if (err) {\n reject(err);\n } else {\n if (!zipfile) {\n reject(new Error(\"zipfile is null\"));\n } else {\n resolve(zipfile);\n }\n }\n });\n });\n\n zipFile.readEntry();\n\n await new Promise<void>((resolve, reject) => {\n zipFile.on(\"end\", (err?: Error) => {\n setImmediate(() => {\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"unzip done\");\n }\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n\n zipFile.on(\"entry\", (entry: yauzl.Entry) => {\n zipFile.openReadStream(entry, (err?: Error | null, readStream?: Readable) => {\n if (err) {\n return reject(err);\n }\n\n const file = path.join(opensslFolder, entry.fileName);\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(\" unzipping :\", file);\n }\n\n const writeStream = fs.createWriteStream(file, \"binary\");\n // ensure parent directory exists\n readStream?.pipe(writeStream);\n\n writeStream.on(\"close\", () => {\n zipFile.readEntry();\n });\n });\n });\n });\n }\n\n const opensslFolder = get_openssl_folder_win32();\n const opensslExecPath = get_openssl_exec_path_win32();\n\n if (!fs.existsSync(opensslFolder)) {\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"creating openssl_folder\", opensslFolder);\n }\n fs.mkdirSync(opensslFolder);\n }\n\n const { opensslOk, version: _version } = await check_openssl_win32();\n\n if (!opensslOk) {\n warningLog(chalk.yellow(\"openssl seems to be missing and need to be installed\"));\n const { downloadedFile } = await download_openssl();\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"deflating \", chalk.yellow(downloadedFile));\n }\n await unzip_openssl(downloadedFile);\n\n const opensslExists = !!fs.existsSync(opensslExecPath);\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"verifying \", opensslExists, opensslExists ? chalk.green(\"OK \") : chalk.red(\" Error\"), opensslExecPath);\n }\n\n const _opensslExecPath2 = await check_openssl_win32();\n return opensslExecPath;\n } else {\n // istanbul ignore next\n if (doDebug) {\n warningLog(chalk.green(\"openssl is already installed and have the expected version.\"));\n }\n return opensslExecPath;\n }\n}\n\n/**\n *\n * return path to the openssl executable\n */\nexport async function install_prerequisite(): Promise<string> {\n // istanbul ignore else\n if (process.platform !== \"win32\") {\n return await check_system_openssl_version();\n } else {\n return await install_and_check_win32_openssl_version();\n }\n}\n\nexport async function get_openssl_exec_path(): Promise<string> {\n if (process.platform === \"win32\") {\n const opensslExecPath = await install_prerequisite();\n if (!fs.existsSync(opensslExecPath)) {\n throw new Error(`internal error cannot find ${opensslExecPath}`);\n }\n return opensslExecPath;\n } else {\n return \"openssl\";\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { Filename } from \"../common\";\nimport { quote } from \"../common\";\nimport { makePath } from \"../common2\";\nimport { g_config } from \"../config\";\nimport { getEnv, getEnvironmentVarNames } from \"./_env\";\nimport { type ExecuteOptions, execute_openssl } from \"./execute_openssl\";\n\nfunction openssl_require2DigitYearInDate() {\n // istanbul ignore next\n if (!g_config.opensslVersion) {\n throw new Error(\n \"openssl_require2DigitYearInDate : openssl version is not known:\" + \" please call ensure_openssl_installed()\"\n );\n }\n return g_config.opensslVersion.match(/OpenSSL 0\\.9/);\n}\n\ng_config.opensslVersion = \"\";\n\nlet _counter = 0;\n\nexport function generateStaticConfig(configPath: string, options?: ExecuteOptions) {\n const prePath = options?.cwd || \"\";\n\n const originalFilename = !path.isAbsolute(configPath) ? path.join(prePath, configPath) : configPath;\n let staticConfig = fs.readFileSync(originalFilename, { encoding: \"utf8\" });\n for (const envVar of getEnvironmentVarNames()) {\n staticConfig = staticConfig.replace(new RegExp(envVar.pattern, \"gi\"), getEnv(envVar.key));\n }\n const staticConfigPath = `${configPath}.${process.pid}-${_counter++}.tmp`;\n const temporaryConfigPath = !path.isAbsolute(configPath) ? path.join(prePath, staticConfigPath) : staticConfigPath;\n fs.writeFileSync(temporaryConfigPath, staticConfig);\n if (options?.cwd) {\n return path.relative(options.cwd, temporaryConfigPath);\n } else {\n return temporaryConfigPath;\n }\n}\n\nconst q = quote;\nconst n = makePath;\n\n/**\n * calculate the public key from private key\n * openssl rsa -pubout -in private_key.pem\n *\n * @method getPublicKeyFromPrivateKey\n * @param privateKeyFilename: the existing file with the private key\n * @param publicKeyFilename: the file where to store the public key\n */\nexport async function getPublicKeyFromPrivateKey(privateKeyFilename: string, publicKeyFilename: string): Promise<void> {\n assert(fs.existsSync(privateKeyFilename));\n await execute_openssl(`rsa -pubout -in ${q(n(privateKeyFilename))} -out ${q(n(publicKeyFilename))}`, {});\n}\n\n/**\n * extract public key from a certificate\n * openssl x509 -pubkey -in certificate.pem -nottext\n *\n * @method getPublicKeyFromCertificate\n * @param certificateFilename\n * @param publicKeyFilename\n */\nexport async function getPublicKeyFromCertificate(certificateFilename: string, publicKeyFilename: string) {\n assert(fs.existsSync(certificateFilename));\n await execute_openssl(`x509 -pubkey -in ${q(n(certificateFilename))} > ${q(n(publicKeyFilename))}`, {});\n}\nexport function x509Date(date?: Date): string {\n date = date || new Date();\n const Y = date.getUTCFullYear();\n const M = date.getUTCMonth() + 1;\n const D = date.getUTCDate();\n const h = date.getUTCHours();\n const m = date.getUTCMinutes();\n const s = date.getUTCSeconds();\n\n function w(s: string | number, l: number): string {\n return `${s}`.padStart(l, \"0\");\n }\n\n if (openssl_require2DigitYearInDate()) {\n // for example: on MacOS , where openssl 0.98 is installed by default\n return `${w(Y, 2) + w(M, 2) + w(D, 2) + w(h, 2) + w(m, 2) + w(s, 2)}Z`;\n } else {\n // for instance when openssl version is greater than 1.0.0\n return `${w(Y, 4) + w(M, 2) + w(D, 2) + w(h, 2) + w(m, 2) + w(s, 2)}Z`;\n }\n}\n\n/**\n * @param certificate - the certificate file in PEM format, file must exist\n */\nexport async function dumpCertificate(certificate: Filename): Promise<string> {\n assert(fs.existsSync(certificate));\n return await execute_openssl(`x509 -in ${q(n(certificate))} -text -noout`, {});\n}\n\nexport async function toDer(certificatePem: string): Promise<string> {\n assert(fs.existsSync(certificatePem));\n const certificateDer = certificatePem.replace(\".pem\", \".der\");\n return await execute_openssl(`x509 -outform der -in ${certificatePem} -out ${certificateDer}`, {});\n}\n\nexport async function fingerprint(certificatePem: string): Promise<string> {\n // openssl x509 -in my_certificate.pem -hash -dates -noout -fingerprint\n assert(fs.existsSync(certificatePem));\n return await execute_openssl(`x509 -fingerprint -noout -in ${certificatePem}`, {});\n}\n","const config =\n \"#.........DO NOT MODIFY BY HAND .........................\\n\" +\n \"[ ca ]\\n\" +\n \"default_ca = CA_default\\n\" +\n \"[ CA_default ]\\n\" +\n \"dir = %%ROOT_FOLDER%% # the main CA folder\\n\" +\n \"certs = $dir/certs # where to store certificates\\n\" +\n \"new_certs_dir = $dir/certs #\\n\" +\n \"database = $dir/index.txt # the certificate database\\n\" +\n \"serial = $dir/serial # the serial number counter\\n\" +\n \"certificate = $dir/public/cacert.pem # The root CA certificate\\n\" +\n \"private_key = $dir/private/cakey.pem # the CA private key\\n\" +\n \"x509_extensions = usr_cert #\\n\" +\n \"default_days = 3650 # default validity : 10 years\\n\" +\n \"\\n\" +\n \"# default_md = sha1\\n\" +\n \"\\n\" +\n \"default_md = sha256 # The default digest algorithm\\n\" +\n \"\\n\" +\n \"preserve = no\\n\" +\n \"policy = policy_match\\n\" +\n \"# randfile = $dir/random.rnd\\n\" +\n \"# default_startdate = YYMMDDHHMMSSZ\\n\" +\n \"# default_enddate = YYMMDDHHMMSSZ\\n\" +\n \"crl_dir = $dir/crl\\n\" +\n \"crl_extensions = crl_ext\\n\" +\n \"crl = $dir/revocation_list.crl # the Revocation list\\n\" +\n \"crlnumber = $dir/crlnumber # CRL number file\\n\" +\n \"default_crl_days = 30\\n\" +\n \"default_crl_hours = 24\\n\" +\n \"#msie_hack\\n\" +\n \"\\n\" +\n \"[ policy_match ]\\n\" +\n \"countryName = optional\\n\" +\n \"stateOrProvinceName = optional\\n\" +\n \"localityName = optional\\n\" +\n \"organizationName = optional\\n\" +\n \"organizationalUnitName = optional\\n\" +\n \"commonName = optional\\n\" +\n \"emailAddress = optional\\n\" +\n \"\\n\" +\n \"[ req ]\\n\" +\n \"default_bits = 4096 # Size of keys\\n\" +\n \"default_keyfile = key.pem # name of generated keys\\n\" +\n \"distinguished_name = req_distinguished_name\\n\" +\n \"attributes = req_attributes\\n\" +\n \"x509_extensions = v3_ca\\n\" +\n \"#input_password\\n\" +\n \"#output_password\\n\" +\n \"string_mask = nombstr # permitted characters\\n\" +\n \"req_extensions = v3_req\\n\" +\n \"\\n\" +\n \"[ req_distinguished_name ]\\n\" +\n \"\\n\" +\n \"#0 countryName = Country Name (2 letter code)\\n\" +\n \"# countryName_default = FR\\n\" +\n \"# countryName_min = 2\\n\" +\n \"# countryName_max = 2\\n\" +\n \"# stateOrProvinceName = State or Province Name (full name)\\n\" +\n \"# stateOrProvinceName_default = Ile de France\\n\" +\n \"# localityName = Locality Name (city, district)\\n\" +\n \"# localityName_default = Paris\\n\" +\n \"organizationName = Organization Name (company)\\n\" +\n \"organizationName_default = NodeOPCUA\\n\" +\n \"# organizationalUnitName = Organizational Unit Name (department, division)\\n\" +\n \"# organizationalUnitName_default = R&D\\n\" +\n \"commonName = Common Name (hostname, FQDN, IP, or your name)\\n\" +\n \"commonName_max = 256\\n\" +\n \"commonName_default = NodeOPCUA\\n\" +\n \"# emailAddress = Email Address\\n\" +\n \"# emailAddress_max = 40\\n\" +\n \"# emailAddress_default = node-opcua (at) node-opcua (dot) com\\n\" +\n \"\\n\" +\n \"[ req_attributes ]\\n\" +\n \"#challengePassword = A challenge password\\n\" +\n \"#challengePassword_min = 4\\n\" +\n \"#challengePassword_max = 20\\n\" +\n \"#unstructuredName = An optional company name\\n\" +\n \"[ usr_cert ]\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid,issuer:always\\n\" +\n \"#authorityKeyIdentifier = keyid\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"# issuerAltName = issuer:copy\\n\" +\n \"nsComment = ''OpenSSL Generated Certificate''\\n\" +\n \"#nsCertType = client, email, objsign for ''everything including object signing''\\n\" +\n \"#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem\\n\" +\n \"#nsBaseUrl =\\n\" +\n \"#nsRenewalUrl =\\n\" +\n \"#nsCaPolicyUrl =\\n\" +\n \"#nsSslServerName =\\n\" +\n \"keyUsage = critical, digitalSignature, nonRepudiation,\" +\n \" keyEncipherment, dataEncipherment, keyAgreement, keyCertSign\\n\" +\n \"extendedKeyUsage = critical,serverAuth ,clientAuth\\n\" +\n \"\\n\" +\n \"[ v3_req ]\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement\\n\" +\n \"extendedKeyUsage = critical,serverAuth ,clientAuth\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n 'nsComment = \"CA Generated by Node-OPCUA Certificate utility using openssl\"\\n' +\n \"[ v3_ca ]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid:always,issuer:always\\n\" +\n \"# authorityKeyIdentifier = keyid\\n\" +\n \"basicConstraints = CA:TRUE\\n\" +\n \"keyUsage = critical, cRLSign, keyCertSign\\n\" +\n 'nsComment = \"CA Certificate generated by Node-OPCUA Certificate utility using openssl\"\\n' +\n \"#nsCertType = sslCA, emailCA\\n\" +\n \"#subjectAltName = email:copy\\n\" +\n \"#issuerAltName = issuer:copy\\n\" +\n \"#obj = DER:02:03\\n\" +\n \"crlDistributionPoints = @crl_info\\n\" +\n \"[ crl_info ]\\n\" +\n \"URI.0 = http://localhost:8900/crl.pem\\n\" +\n \"[ v3_selfsigned]\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement\\n\" +\n \"extendedKeyUsage = critical,serverAuth ,clientAuth\\n\" +\n 'nsComment = \"Self-signed certificate, generated by NodeOPCUA\"\\n' +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"\\n\" +\n \"[ crl_ext ]\\n\" +\n \"#issuerAltName = issuer:copy\\n\" +\n \"authorityKeyIdentifier = keyid:always,issuer:always\\n\" +\n \"#authorityInfoAccess = @issuer_info\";\n\nexport default config;\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// Error.stackTraceLimit = Infinity;\n// tslint:disable:variable-name\n// tslint:disable:no-console\n// tslint:disable:object-literal-sort-keys\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport { CertificatePurpose, generatePrivateKeyFile, Subject, type SubjectOptions } from \"node-opcua-crypto\";\n\nimport { makeApplicationUrn } from \"../misc/applicationurn\";\nimport { extractFullyQualifiedDomainName, getFullyQualifiedDomainName } from \"../misc/hostname\";\nimport { CertificateManager, type CreateSelfSignCertificateParam1 } from \"../pki/certificate_manager\";\nimport {\n type CreateCertificateSigningRequestWithConfigOptions,\n debugLog,\n displayChapter,\n displaySubtitle,\n displayTitle,\n type Filename,\n g_config,\n type KeySize,\n makePath,\n mkdirRecursiveSync,\n warningLog\n} from \"../toolbox\";\nimport {\n createCertificateSigningRequestWithOpenSSL,\n dumpCertificate,\n ensure_openssl_installed,\n fingerprint,\n getPublicKeyFromPrivateKey,\n setEnv,\n toDer\n} from \"../toolbox/with_openssl\";\nimport { CertificateAuthority, defaultSubject } from \"./certificate_authority\";\n\nconst epilog = \"Copyright (c) sterfive - node-opcua - 2017-2026\";\n\n// ------------------------------------------------- some useful dates\nfunction get_offset_date(date: Date, nbDays: number): Date {\n const d = new Date(date.getTime());\n d.setDate(d.getDate() + nbDays);\n return d;\n}\n\nconst today = new Date();\nconst yesterday = get_offset_date(today, -1);\nconst two_years_ago = get_offset_date(today, -2 * 365);\nconst next_year = get_offset_date(today, 365);\n\ninterface LocalConfig {\n CAFolder?: string;\n PKIFolder?: string;\n\n keySize?: KeySize;\n\n subject?: SubjectOptions | string;\n\n certificateDir?: Filename;\n\n privateKey?: Filename;\n\n applicationUri?: string;\n\n outputFile?: string;\n\n altNames?: string[];\n dns?: string[];\n ip?: string[];\n\n startDate?: Date;\n validity?: number;\n}\n\nlet gLocalConfig: LocalConfig = {};\n\nlet g_certificateAuthority: CertificateAuthority; // the Certificate Authority\n\n/***\n *\n *\n * prerequisites :\n * g_config.CAFolder : the folder of the CA\n */\nasync function construct_CertificateAuthority(subject: string) {\n // verify that g_config file has been loaded\n assert(typeof gLocalConfig.CAFolder === \"string\", \"expecting a CAFolder in config\");\n assert(typeof gLocalConfig.keySize === \"number\", \"expecting a keySize in config\");\n\n if (!g_certificateAuthority) {\n g_certificateAuthority = new CertificateAuthority({\n keySize: gLocalConfig.keySize,\n location: gLocalConfig.CAFolder,\n subject\n });\n await g_certificateAuthority.initialize();\n }\n}\n\nlet certificateManager: CertificateManager; // the Certificate Manager\n/***\n *\n *\n * prerequisites :\n * g_config.PKIFolder : the folder of the PKI\n */\nasync function construct_CertificateManager() {\n assert(typeof gLocalConfig.PKIFolder === \"string\", \"expecting a PKIFolder in config\");\n\n if (!certificateManager) {\n certificateManager = new CertificateManager({\n keySize: gLocalConfig.keySize,\n location: gLocalConfig.PKIFolder\n });\n await certificateManager.initialize();\n }\n}\n\nfunction _displayConfig(config: { [key: string]: { toString: () => string } }) {\n function w(str: string, l: number): string {\n return `${str} `.substring(0, l);\n }\n\n warningLog(chalk.yellow(\" configuration = \"));\n\n for (const [key, value] of Object.entries(config)) {\n warningLog(` ${chalk.yellow(w(key, 30))} : ${chalk.cyan(value.toString())}`);\n }\n}\n\nfunction default_template_content(): string {\n // istanbul ignore next\n if ((process as unknown as { pkg?: { entrypoint: string } }).pkg?.entrypoint) {\n // we are using PKG compiled package !\n\n // warningLog(\"___filename\", __filename);\n // warningLog(\"__dirname\", __dirname);\n // warningLog(\"process.pkg.entrypoint\", (process as unknown as IReadConfigurationOpts).pkg.entrypoint);\n const a = fs.readFileSync(path.join(__dirname, \"../../bin/pki_config.example.js\"), \"utf8\");\n return a;\n }\n function find_default_config_template() {\n const rootFolder = find_module_root_folder();\n\n // Note: we use a hardcoded config filename here because after tsup bundling,\n // __filename points to the bundle file (e.g., \"index.mjs\") rather than the\n // original source file, making dynamic name construction unreliable.\n const configName = \"pki_config.example.js\";\n\n let default_config_template = path.join(rootFolder, \"bin\", configName);\n\n if (!fs.existsSync(default_config_template)) {\n default_config_template = path.join(__dirname, \"..\", configName);\n\n if (!fs.existsSync(default_config_template)) {\n default_config_template = path.join(__dirname, `../bin/${configName}`);\n }\n }\n return default_config_template;\n }\n const default_config_template = find_default_config_template();\n assert(fs.existsSync(default_config_template));\n const default_config_template_content = fs.readFileSync(default_config_template, \"utf8\");\n return default_config_template_content;\n}\n\n/**\n *\n */\nfunction find_module_root_folder() {\n let rootFolder = path.join(__dirname);\n\n for (let i = 0; i < 4; i++) {\n if (fs.existsSync(path.join(rootFolder, \"package.json\"))) {\n return rootFolder;\n }\n rootFolder = path.join(rootFolder, \"..\");\n }\n\n assert(fs.existsSync(path.join(rootFolder, \"package.json\")), \"root folder must have a package.json file\");\n return rootFolder;\n}\n\ninterface IReadConfigurationOpts {\n root: string;\n silent?: boolean;\n subject?: string;\n CAFolder?: string;\n PKIFolder?: string;\n privateKey?: string;\n applicationUri?: string;\n output?: string;\n altNames?: string;\n dns?: string;\n ip?: string;\n keySize?: KeySize;\n validity?: number;\n}\n\n/* eslint complexity:off, max-statements:off */\nasync function readConfiguration(argv: IReadConfigurationOpts) {\n if (argv.silent) {\n g_config.silent = true;\n } else {\n g_config.silent = false;\n }\n\n const fqdn = await extractFullyQualifiedDomainName();\n const hostname = os.hostname();\n let certificateDir: string;\n\n function performSubstitution(str: string): string {\n str = str.replace(\"{CWD}\", process.cwd());\n if (certificateDir) {\n str = str.replace(\"{root}\", certificateDir);\n }\n if (gLocalConfig?.PKIFolder) {\n str = str.replace(\"{PKIFolder}\", gLocalConfig.PKIFolder);\n }\n str = str.replace(\"{hostname}\", hostname);\n str = str.replace(\"%FQDN%\", fqdn);\n return str;\n }\n\n function prepare(file: Filename): Filename {\n const tmp = path.resolve(performSubstitution(file));\n return makePath(tmp);\n }\n\n // ------------------------------------------------------------------------------------------------------------\n certificateDir = argv.root;\n assert(typeof certificateDir === \"string\");\n\n certificateDir = prepare(certificateDir);\n mkdirRecursiveSync(certificateDir);\n assert(fs.existsSync(certificateDir));\n\n // ------------------------------------------------------------------------------------------------------------\n const default_config = path.join(certificateDir, \"config.js\");\n\n if (!fs.existsSync(default_config)) {\n // copy\n debugLog(chalk.yellow(\" Creating default g_config file \"), chalk.cyan(default_config));\n const default_config_template_content = default_template_content();\n fs.writeFileSync(default_config, default_config_template_content);\n } else {\n debugLog(chalk.yellow(\" using g_config file \"), chalk.cyan(default_config));\n }\n if (!fs.existsSync(default_config)) {\n debugLog(chalk.redBright(\" cannot find config file \", default_config));\n }\n\n // see http://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean\n // set random file to be random.rnd in the same folder as the g_config file\n const defaultRandomFile = path.join(path.dirname(default_config), \"random.rnd\");\n setEnv(\"RANDFILE\", defaultRandomFile);\n\n /* eslint global-require: 0*/\n const _require = createRequire(__filename);\n gLocalConfig = _require(default_config);\n\n gLocalConfig.subject = new Subject(gLocalConfig.subject || \"\");\n\n // if subject is provided on the command line , it has hight priority\n if (argv.subject) {\n gLocalConfig.subject = new Subject(argv.subject);\n }\n\n // istanbul ignore next\n if (!gLocalConfig.subject.commonName) {\n throw new Error(\"subject must have a Common Name\");\n }\n\n gLocalConfig.certificateDir = certificateDir;\n\n // ------------------------------------------------------------------------------------------------------------\n let CAFolder = argv.CAFolder || path.join(certificateDir, \"CA\");\n CAFolder = prepare(CAFolder);\n gLocalConfig.CAFolder = CAFolder;\n\n // ------------------------------------------------------------------------------------------------------------\n gLocalConfig.PKIFolder = path.join(gLocalConfig.certificateDir, \"PKI\");\n if (argv.PKIFolder) {\n gLocalConfig.PKIFolder = prepare(argv.PKIFolder);\n }\n gLocalConfig.PKIFolder = prepare(gLocalConfig.PKIFolder);\n if (argv.privateKey) {\n gLocalConfig.privateKey = prepare(argv.privateKey);\n }\n\n if (argv.applicationUri) {\n gLocalConfig.applicationUri = performSubstitution(argv.applicationUri);\n }\n\n if (argv.output) {\n gLocalConfig.outputFile = argv.output;\n }\n\n gLocalConfig.altNames = [];\n if (argv.altNames) {\n gLocalConfig.altNames = argv.altNames.split(\";\");\n }\n gLocalConfig.dns = [getFullyQualifiedDomainName()];\n if (argv.dns) {\n gLocalConfig.dns = argv.dns.split(\",\").map(performSubstitution);\n }\n gLocalConfig.ip = [];\n if (argv.ip) {\n gLocalConfig.ip = argv.ip.split(\",\");\n }\n if (argv.keySize) {\n const v = argv.keySize;\n if (v !== 1024 && v !== 2048 && v !== 3072 && v !== 4096) {\n throw new Error(`invalid keysize specified ${v} should be 1024,2048,3072 or 4096`);\n }\n gLocalConfig.keySize = argv.keySize;\n }\n\n if (argv.validity) {\n gLocalConfig.validity = argv.validity;\n }\n // xx displayConfig(g_config);\n // ------------------------------------------------------------------------------------------------------------\n}\n\nasync function createDefaultCertificate(\n base_name: string,\n prefix: string,\n key_length: KeySize,\n applicationUri: string,\n dev: boolean\n) {\n // possible key length in bits\n assert(key_length === 1024 || key_length === 2048 || key_length === 3072 || key_length === 4096);\n\n const private_key_file = makePath(base_name, `${prefix}key_${key_length}.pem`);\n const public_key_file = makePath(base_name, `${prefix}public_key_${key_length}.pub`);\n const certificate_file = makePath(base_name, `${prefix}cert_${key_length}.pem`);\n const certificate_file_outofdate = makePath(base_name, `${prefix}cert_${key_length}_outofdate.pem`);\n const certificate_file_not_active_yet = makePath(base_name, `${prefix}cert_${key_length}_not_active_yet.pem`);\n const certificate_revoked = makePath(base_name, `${prefix}cert_${key_length}_revoked.pem`);\n const self_signed_certificate_file = makePath(base_name, `${prefix}selfsigned_cert_${key_length}.pem`);\n\n const fqdn = getFullyQualifiedDomainName();\n const hostname = os.hostname();\n const dns: string[] = [\n // for conformance reason, localhost shall not be present in the DNS field of COP\n // ***FORBIDEN** \"localhost\",\n getFullyQualifiedDomainName()\n ];\n if (hostname !== fqdn) {\n dns.push(hostname);\n }\n\n const ip: string[] = [];\n\n async function createCertificateIfNotExist(\n certificate: Filename,\n private_key: Filename,\n applicationUri: string,\n startDate: Date,\n validity: number\n ): Promise<string> {\n // istanbul ignore next\n if (fs.existsSync(certificate)) {\n warningLog(chalk.yellow(\" certificate\"), chalk.cyan(certificate), chalk.yellow(\" already exists => skipping\"));\n return \"\";\n } else {\n return await createCertificate(certificate, private_key, applicationUri, startDate, validity);\n }\n }\n\n async function createCertificate(\n certificate: Filename,\n privateKey: Filename,\n applicationUri: string,\n startDate: Date,\n validity: number\n ): Promise<string> {\n const certificateSigningRequestFile = `${certificate}.csr`;\n\n const configFile = makePath(base_name, \"../certificates/PKI/own/openssl.cnf\");\n\n const dns = [os.hostname()];\n const ip = [\"127.0.0.1\"];\n\n const params: CreateCertificateSigningRequestWithConfigOptions = {\n applicationUri,\n privateKey,\n rootDir: \".\",\n configFile,\n dns,\n ip,\n purpose: CertificatePurpose.ForApplication\n };\n\n // create CSR\n await createCertificateSigningRequestWithOpenSSL(certificateSigningRequestFile, params);\n\n return await g_certificateAuthority.signCertificateRequest(certificate, certificateSigningRequestFile, {\n applicationUri,\n dns,\n ip,\n startDate,\n validity\n });\n }\n\n async function createSelfSignedCertificate(\n certificate: Filename,\n private_key: Filename,\n applicationUri: string,\n startDate: Date,\n validity: number\n ) {\n await g_certificateAuthority.createSelfSignedCertificate(certificate, private_key, {\n applicationUri,\n dns,\n ip,\n startDate,\n validity\n });\n }\n\n async function revoke_certificate(certificate: Filename) {\n await g_certificateAuthority.revokeCertificate(certificate, {});\n }\n\n async function createPrivateKeyIfNotExist(privateKey: Filename, keyLength: KeySize) {\n if (fs.existsSync(privateKey)) {\n warningLog(chalk.yellow(\" privateKey\"), chalk.cyan(privateKey), chalk.yellow(\" already exists => skipping\"));\n return;\n } else {\n await generatePrivateKeyFile(privateKey, keyLength);\n }\n }\n\n displaySubtitle(` create private key :${private_key_file}`);\n\n await createPrivateKeyIfNotExist(private_key_file, key_length);\n displaySubtitle(` extract public key ${public_key_file} from private key `);\n await getPublicKeyFromPrivateKey(private_key_file, public_key_file);\n displaySubtitle(` create Certificate ${certificate_file}`);\n\n await createCertificateIfNotExist(certificate_file, private_key_file, applicationUri, yesterday, 365);\n\n displaySubtitle(` create self signed Certificate ${self_signed_certificate_file}`);\n\n if (fs.existsSync(self_signed_certificate_file)) {\n // self_signed certificate already exists\n return;\n }\n await createSelfSignedCertificate(self_signed_certificate_file, private_key_file, applicationUri, yesterday, 365);\n\n if (dev) {\n await createCertificateIfNotExist(certificate_file_outofdate, private_key_file, applicationUri, two_years_ago, 365);\n\n await createCertificateIfNotExist(certificate_file_not_active_yet, private_key_file, applicationUri, next_year, 365);\n\n if (!fs.existsSync(certificate_revoked)) {\n // self_signed certificate already exists\n const certificate = await createCertificateIfNotExist(\n certificate_revoked,\n private_key_file,\n `${applicationUri}Revoked`, // make sure we used a uniq URI here\n yesterday,\n 365\n );\n warningLog(\" certificate to revoke => \", certificate);\n revoke_certificate(certificate_revoked);\n }\n }\n}\n\nasync function wrap(func: () => Promise<void>) {\n try {\n await func();\n } catch (err) {\n console.log((err as Error).message);\n }\n}\n\nasync function create_default_certificates(dev: boolean) {\n assert(gLocalConfig);\n const base_name = gLocalConfig.certificateDir || \"\";\n assert(fs.existsSync(base_name));\n\n let clientURN: string;\n let serverURN: string;\n let discoveryServerURN: string;\n wrap(async () => {\n await extractFullyQualifiedDomainName();\n const hostname = os.hostname();\n const fqdn = getFullyQualifiedDomainName();\n warningLog(chalk.yellow(\" hostname = \"), chalk.cyan(hostname));\n warningLog(chalk.yellow(\" fqdn = \"), chalk.cyan(fqdn));\n clientURN = makeApplicationUrn(hostname, \"NodeOPCUA-Client\");\n serverURN = makeApplicationUrn(hostname, \"NodeOPCUA-Server\");\n discoveryServerURN = makeApplicationUrn(hostname, \"NodeOPCUA-DiscoveryServer\");\n\n displayTitle(\"Create Application Certificate for Server & its private key\");\n await createDefaultCertificate(base_name, \"client_\", 1024, clientURN, dev);\n await createDefaultCertificate(base_name, \"client_\", 2048, clientURN, dev);\n await createDefaultCertificate(base_name, \"client_\", 3072, clientURN, dev);\n await createDefaultCertificate(base_name, \"client_\", 4096, clientURN, dev);\n\n displayTitle(\"Create Application Certificate for Client & its private key\");\n await createDefaultCertificate(base_name, \"server_\", 1024, serverURN, dev);\n await createDefaultCertificate(base_name, \"server_\", 2048, serverURN, dev);\n await createDefaultCertificate(base_name, \"server_\", 3072, serverURN, dev);\n await createDefaultCertificate(base_name, \"server_\", 4096, serverURN, dev);\n\n displayTitle(\"Create Application Certificate for DiscoveryServer & its private key\");\n await createDefaultCertificate(base_name, \"discoveryServer_\", 1024, discoveryServerURN, dev);\n await createDefaultCertificate(base_name, \"discoveryServer_\", 2048, discoveryServerURN, dev);\n await createDefaultCertificate(base_name, \"discoveryServer_\", 3072, discoveryServerURN, dev);\n await createDefaultCertificate(base_name, \"discoveryServer_\", 4096, discoveryServerURN, dev);\n });\n}\n\nasync function createDefaultCertificates(dev: boolean) {\n await construct_CertificateAuthority(\"\");\n await construct_CertificateManager();\n await create_default_certificates(dev);\n}\n\nimport commandLineArgs from \"command-line-args\";\nimport commandLineUsage from \"command-line-usage\";\n\nconst commonOptions = [\n {\n name: \"root\",\n alias: \"r\",\n type: String,\n defaultValue: \"{CWD}/certificates\",\n description: \"the location of the Certificate folder\"\n },\n {\n name: \"CAFolder\",\n alias: \"c\",\n type: String,\n defaultValue: \"{root}/CA\",\n description: \"the location of the Certificate Authority folder\"\n },\n { name: \"PKIFolder\", type: String, defaultValue: \"{root}/PKI\", description: \"the location of the Public Key Infrastructure\" },\n { name: \"silent\", type: Boolean, defaultValue: false, description: \"minimize output\" },\n {\n name: \"privateKey\",\n alias: \"p\",\n type: String,\n defaultValue: \"{PKIFolder}/own/private_key.pem\",\n description: \"the private key to use to generate certificate\"\n },\n {\n name: \"keySize\",\n alias: \"k\",\n type: Number,\n defaultValue: 2048,\n description: \"the private key size in bits (1024|2048|3072|4096)\"\n },\n { name: \"help\", alias: \"h\", type: Boolean, description: \"display this help\" }\n];\n\nfunction getOptions(names: string[]) {\n return commonOptions.filter((o) => names.includes(o.name) || o.name === \"help\" || o.name === \"silent\");\n}\n\nfunction showHelp(command: string, description: string, options: Record<string, unknown>[], usage?: string) {\n const sections = [\n {\n header: `Command: ${command}`,\n content: description\n },\n {\n header: \"Usage\",\n content: usage || `$0 ${command} [options]`\n },\n {\n header: \"Options\",\n optionList: options\n }\n ];\n console.log(commandLineUsage(sections));\n}\n\nexport async function main(argumentsList: string | string[]) {\n const mainDefinitions = [{ name: \"command\", defaultOption: true }];\n let mainOptions: commandLineArgs.CommandLineOptions;\n try {\n mainOptions = commandLineArgs(mainDefinitions, { argv: argumentsList as string[], stopAtFirstUnknown: true });\n } catch (err) {\n console.log((err as Error).message);\n return;\n }\n\n const argv = mainOptions._unknown || [];\n const command = mainOptions.command;\n\n if (!command || command === \"help\") {\n console.log(\n commandLineUsage([\n {\n header: \"node-opcua-pki\",\n content: `PKI management for node-opcua\\n\\n${epilog}`\n },\n {\n header: \"Commands\",\n content: [\n { name: \"demo\", summary: \"create default certificate for node-opcua demos\" },\n { name: \"createCA\", summary: \"create a Certificate Authority\" },\n { name: \"createPKI\", summary: \"create a Public Key Infrastructure\" },\n { name: \"certificate\", summary: \"create a new certificate\" },\n { name: \"revoke <certificateFile>\", summary: \"revoke a existing certificate\" },\n { name: \"csr\", summary: \"create a certificate signing request\" },\n { name: \"sign\", summary: \"validate a certificate signing request and generate a certificate\" },\n { name: \"dump <certificateFile>\", summary: \"display a certificate\" },\n { name: \"toder <pemCertificate>\", summary: \"convert a certificate to a DER format with finger print\" },\n { name: \"fingerprint <certificateFile>\", summary: \"print the certificate fingerprint\" },\n { name: \"version\", summary: \"display the version number\" }\n ]\n }\n ])\n );\n return;\n }\n\n if (command === \"version\") {\n const rootFolder = find_module_root_folder();\n const pkg = JSON.parse(fs.readFileSync(path.join(rootFolder, \"package.json\"), \"utf-8\"));\n console.log(pkg.version);\n return;\n }\n\n if (command === \"demo\") {\n const optionsDef = [\n ...getOptions([\"root\", \"silent\"]),\n { name: \"dev\", type: Boolean, description: \"create all sort of fancy certificates for dev testing purposes\" },\n { name: \"clean\", type: Boolean, description: \"Purge existing directory [use with care!]\" }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help)\n return showHelp(\n \"demo\",\n \"create default certificate for node-opcua demos\",\n optionsDef,\n \"$0 demo [--dev] [--silent] [--clean]\"\n );\n\n await wrap(async () => {\n await ensure_openssl_installed();\n displayChapter(\"Create Demo certificates\");\n displayTitle(\"reading configuration\");\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n if (local_argv.clean) {\n displayTitle(\"Cleaning old certificates\");\n assert(gLocalConfig);\n const certificateDir = gLocalConfig.certificateDir || \"\";\n const files = await fs.promises.readdir(certificateDir);\n for (const file of files) {\n if (file.includes(\".pem\") || file.includes(\".pub\")) {\n await fs.promises.unlink(path.join(certificateDir, file));\n }\n }\n mkdirRecursiveSync(certificateDir);\n }\n displayTitle(\"create certificates\");\n await createDefaultCertificates(local_argv.dev);\n displayChapter(\"Demo certificates CREATED\");\n });\n return;\n }\n\n if (command === \"createCA\") {\n const optionsDef = [\n ...getOptions([\"root\", \"CAFolder\", \"keySize\", \"silent\"]),\n { name: \"subject\", type: String, defaultValue: defaultSubject, description: \"the CA certificate subject\" }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help) return showHelp(\"createCA\", \"create a Certificate Authority\", optionsDef);\n\n await wrap(async () => {\n await ensure_openssl_installed();\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n await construct_CertificateAuthority(local_argv.subject);\n });\n return;\n }\n\n if (command === \"createPKI\") {\n const optionsDef = getOptions([\"root\", \"PKIFolder\", \"keySize\", \"silent\"]);\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help) return showHelp(\"createPKI\", \"create a Public Key Infrastructure\", optionsDef);\n\n await wrap(async () => {\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n await construct_CertificateManager();\n });\n return;\n }\n\n if (command === \"certificate\") {\n const optionsDef = [\n ...getOptions([\"root\", \"CAFolder\", \"PKIFolder\", \"privateKey\", \"silent\"]),\n {\n name: \"applicationUri\",\n alias: \"a\",\n type: String,\n defaultValue: \"urn:{hostname}:Node-OPCUA-Server\",\n description: \"the application URI\"\n },\n {\n name: \"output\",\n alias: \"o\",\n type: String,\n defaultValue: \"my_certificate.pem\",\n description: \"the name of the generated certificate =>\"\n },\n {\n name: \"selfSigned\",\n alias: \"s\",\n type: Boolean,\n defaultValue: false,\n description: \"if true, certificate will be self-signed\"\n },\n { name: \"validity\", alias: \"v\", type: Number, description: \"the certificate validity in days\" },\n {\n name: \"dns\",\n type: String,\n defaultValue: \"{hostname}\",\n description: \"the list of valid domain name (comma separated)\"\n },\n { name: \"ip\", type: String, defaultValue: \"\", description: \"the list of valid IPs (comma separated)\" },\n {\n name: \"subject\",\n type: String,\n defaultValue: \"\",\n description: \"the certificate subject ( for instance C=FR/ST=Centre/L=Orleans/O=SomeOrganization/CN=Hello )\"\n }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.applicationUri || !local_argv.output)\n return showHelp(\"certificate\", \"create a new certificate\", optionsDef);\n\n async function command_certificate(local_argv: IReadConfigurationOpts) {\n const selfSigned = !!(local_argv as unknown as { selfSigned?: boolean }).selfSigned;\n if (!selfSigned) {\n await command_full_certificate(local_argv);\n } else {\n await command_selfsigned_certificate(local_argv);\n }\n }\n\n async function command_selfsigned_certificate(local_argv: IReadConfigurationOpts) {\n const _fqdn = await extractFullyQualifiedDomainName();\n await readConfiguration(local_argv);\n await construct_CertificateManager();\n\n displaySubtitle(` create self signed Certificate ${gLocalConfig.outputFile}`);\n let subject =\n local_argv.subject && local_argv.subject.length > 1 ? new Subject(local_argv.subject) : gLocalConfig.subject || \"\";\n\n subject = JSON.parse(JSON.stringify(subject));\n\n const params: CreateSelfSignCertificateParam1 = {\n applicationUri: gLocalConfig.applicationUri || \"\",\n dns: gLocalConfig.dns || [],\n ip: gLocalConfig.ip || [],\n outputFile: gLocalConfig.outputFile || \"self_signed_certificate.pem\",\n startDate: gLocalConfig.startDate || new Date(),\n subject,\n validity: gLocalConfig.validity || 365\n };\n\n await certificateManager.createSelfSignedCertificate(params);\n }\n\n async function command_full_certificate(local_argv: IReadConfigurationOpts) {\n await readConfiguration(local_argv);\n await construct_CertificateManager();\n await construct_CertificateAuthority(\"\");\n assert(fs.existsSync(gLocalConfig.CAFolder || \"\"), \" CA folder must exist\");\n gLocalConfig.privateKey = undefined; // use PKI private key\n // create a Certificate Request from the certificate Manager\n\n gLocalConfig.subject = local_argv.subject && local_argv.subject.length > 1 ? local_argv.subject : gLocalConfig.subject;\n\n const csr_file = await certificateManager.createCertificateRequest(\n gLocalConfig as Parameters<typeof certificateManager.createCertificateRequest>[0]\n );\n if (!csr_file) {\n return;\n }\n warningLog(\" csr_file = \", csr_file);\n const certificate = csr_file.replace(\".csr\", \".pem\");\n\n if (fs.existsSync(certificate)) {\n throw new Error(` File ${certificate} already exist`);\n }\n await g_certificateAuthority.signCertificateRequest(\n certificate,\n csr_file,\n gLocalConfig as Parameters<typeof g_certificateAuthority.signCertificateRequest>[2]\n );\n\n assert(typeof gLocalConfig.outputFile === \"string\");\n fs.writeFileSync(gLocalConfig.outputFile || \"\", fs.readFileSync(certificate, \"ascii\"));\n }\n\n await wrap(async () => await command_certificate(local_argv as unknown as IReadConfigurationOpts));\n return;\n }\n\n if (command === \"revoke\") {\n const optionsDef = [{ name: \"certificateFile\", type: String, defaultOption: true }, ...getOptions([\"root\", \"CAFolder\"])];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.certificateFile)\n return showHelp(\n \"revoke <certificateFile>\",\n \"revoke a existing certificate\",\n optionsDef,\n \"$0 revoke my_certificate.pem\"\n );\n\n async function revoke_certificate(certificate: Filename) {\n await g_certificateAuthority.revokeCertificate(certificate, {});\n }\n\n await wrap(async () => {\n const certificate = path.resolve(local_argv.certificateFile);\n warningLog(chalk.yellow(\" Certificate to revoke : \"), chalk.cyan(certificate));\n if (!fs.existsSync(certificate)) {\n throw new Error(`cannot find certificate to revoke ${certificate}`);\n }\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n await construct_CertificateAuthority(\"\");\n await revoke_certificate(certificate);\n warningLog(\"done ... \");\n warningLog(\" crl = \", g_certificateAuthority.revocationList);\n warningLog(\"\\nyou should now publish the new Certificate Revocation List\");\n });\n return;\n }\n\n if (command === \"csr\") {\n const optionsDef = [\n ...getOptions([\"root\", \"PKIFolder\", \"privateKey\", \"silent\"]),\n {\n name: \"applicationUri\",\n alias: \"a\",\n type: String,\n defaultValue: \"urn:{hostname}:Node-OPCUA-Server\",\n description: \"the application URI\"\n },\n {\n name: \"output\",\n alias: \"o\",\n type: String,\n defaultValue: \"my_certificate_signing_request.csr\",\n description: \"the name of the generated signing_request\"\n },\n {\n name: \"dns\",\n type: String,\n defaultValue: \"{hostname}\",\n description: \"the list of valid domain name (comma separated)\"\n },\n { name: \"ip\", type: String, defaultValue: \"\", description: \"the list of valid IPs (comma separated)\" },\n {\n name: \"subject\",\n type: String,\n defaultValue: \"/CN=Certificate\",\n description: \"the certificate subject ( for instance /C=FR/ST=Centre/L=Orleans/O=SomeOrganization/CN=Hello )\"\n }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help) return showHelp(\"csr\", \"create a certificate signing request\", optionsDef);\n\n await wrap(async () => {\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n if (!fs.existsSync(gLocalConfig.PKIFolder || \"\")) {\n warningLog(\"PKI folder must exist\");\n }\n await construct_CertificateManager();\n if (!gLocalConfig.outputFile || fs.existsSync(gLocalConfig.outputFile)) {\n throw new Error(` File ${gLocalConfig.outputFile} already exist`);\n }\n gLocalConfig.privateKey = undefined; // use PKI private key\n // create a Certificate Request from the certificate Manager\n\n gLocalConfig.subject = local_argv.subject && local_argv.subject.length > 1 ? local_argv.subject : gLocalConfig.subject;\n\n const internal_csr_file = await certificateManager.createCertificateRequest(\n gLocalConfig as Parameters<typeof certificateManager.createCertificateRequest>[0]\n );\n if (!internal_csr_file) {\n return;\n }\n if (!gLocalConfig.outputFile) {\n warningLog(\"please specify a output file\");\n return;\n }\n const csr = await fs.promises.readFile(internal_csr_file, \"utf-8\");\n fs.writeFileSync(gLocalConfig.outputFile || \"\", csr, \"utf-8\");\n\n warningLog(\"Subject = \", gLocalConfig.subject);\n warningLog(\"applicationUri = \", gLocalConfig.applicationUri);\n warningLog(\"altNames = \", gLocalConfig.altNames);\n warningLog(\"dns = \", gLocalConfig.dns);\n warningLog(\"ip = \", gLocalConfig.ip);\n\n warningLog(\"CSR file = \", gLocalConfig.outputFile);\n });\n return;\n }\n\n if (command === \"sign\") {\n const optionsDef = [\n ...getOptions([\"root\", \"CAFolder\", \"silent\"]),\n { name: \"csr\", alias: \"i\", type: String, defaultValue: \"my_certificate_signing_request.csr\", description: \"the csr\" },\n {\n name: \"output\",\n alias: \"o\",\n type: String,\n defaultValue: \"my_certificate.pem\",\n description: \"the name of the generated certificate\"\n },\n { name: \"validity\", alias: \"v\", type: Number, defaultValue: 365, description: \"the certificate validity in days\" }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.csr || !local_argv.output)\n return showHelp(\"sign\", \"validate a certificate signing request and generate a certificate\", optionsDef);\n\n await wrap(async () => {\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n if (!fs.existsSync(gLocalConfig.CAFolder || \"\")) {\n throw new Error(`CA folder must exist:${gLocalConfig.CAFolder}`);\n }\n await construct_CertificateAuthority(\"\");\n const csr_file: string = path.resolve((local_argv as unknown as { csr?: string }).csr || \"\");\n if (!fs.existsSync(csr_file)) {\n throw new Error(`Certificate signing request doesn't exist: ${csr_file}`);\n }\n const certificate = path.resolve(local_argv.output || csr_file.replace(\".csr\", \".pem\"));\n if (fs.existsSync(certificate)) {\n throw new Error(` File ${certificate} already exist`);\n }\n\n await g_certificateAuthority.signCertificateRequest(\n certificate,\n csr_file,\n gLocalConfig as Parameters<typeof g_certificateAuthority.signCertificateRequest>[2]\n );\n\n assert(typeof gLocalConfig.outputFile === \"string\");\n fs.writeFileSync(gLocalConfig.outputFile || \"\", fs.readFileSync(certificate, \"ascii\"));\n });\n return;\n }\n\n if (command === \"dump\") {\n const optionsDef = [\n { name: \"certificateFile\", type: String, defaultOption: true },\n { name: \"help\", alias: \"h\", type: Boolean }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.certificateFile)\n return showHelp(\"dump <certificateFile>\", \"display a certificate\", optionsDef);\n\n await wrap(async () => {\n const data = await dumpCertificate(local_argv.certificateFile);\n warningLog(data);\n });\n return;\n }\n\n if (command === \"toder\") {\n const optionsDef = [\n { name: \"pemCertificate\", type: String, defaultOption: true },\n { name: \"help\", alias: \"h\", type: Boolean }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.pemCertificate)\n return showHelp(\"toder <pemCertificate>\", \"convert a certificate to a DER format with finger print\", optionsDef);\n\n await wrap(async () => {\n await toDer(local_argv.pemCertificate);\n });\n return;\n }\n\n if (command === \"fingerprint\") {\n const optionsDef = [\n { name: \"certificateFile\", type: String, defaultOption: true },\n { name: \"help\", alias: \"h\", type: Boolean }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.certificateFile)\n return showHelp(\"fingerprint <certificateFile>\", \"print the certificate fingerprint\", optionsDef);\n\n await wrap(async () => {\n const certificate = local_argv.certificateFile;\n const data = await fingerprint(certificate);\n if (!data) return;\n const s = data.split(\"=\")[1].split(\":\").join(\"\").trim();\n warningLog(s);\n });\n return;\n }\n\n console.log(`Unknown command: ${command}`);\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\nimport { createHash } from \"node:crypto\";\n\nexport function makeApplicationUrn(hostname: string, suffix: string): string {\n // beware : Openssl doesn't support urn with length greater than 64 !!\n // sometimes hostname length could be too long ...\n // application urn length must not exceed 64 car. to comply with openssl\n // see cryptoCA\n let hostnameHash = hostname;\n if (hostnameHash.length + 7 + suffix.length >= 64) {\n // we need to reduce the applicationUrn side => let's take\n // a portion of the hostname hash.\n hostnameHash = createHash(\"md5\").update(hostname).digest(\"hex\").substring(0, 16);\n }\n\n const applicationUrn = `urn:${hostnameHash}:${suffix}`;\n assert(applicationUrn.length <= 64);\n return applicationUrn;\n}\n","/**\n * @module node-opcua-hostname\n */\nimport dns from \"node:dns\";\nimport os from \"node:os\";\nimport { promisify } from \"node:util\";\n\nfunction trim(str: string, length?: number): string {\n if (!length) {\n return str;\n }\n return str.substring(0, Math.min(str.length, length));\n}\n\nfunction fqdn(callback: (err: Error | null, fqdn?: string) => void) {\n const uqdn = os.hostname();\n\n dns.lookup(uqdn, { hints: dns.ADDRCONFIG }, (err1: Error | null, ip: string) => {\n if (err1) {\n return callback(err1);\n }\n\n dns.lookupService(ip, 0, (err2: Error | null, _fqdn: string) => {\n if (err2) {\n return callback(err2);\n }\n _fqdn = _fqdn.replace(\".localdomain\", \"\");\n callback(null, _fqdn);\n });\n });\n}\n\nlet _fullyQualifiedDomainNameInCache: string | undefined;\n\n/**\n * extract FullyQualifiedDomainName of this computer\n */\nexport async function extractFullyQualifiedDomainName(): Promise<string> {\n if (_fullyQualifiedDomainNameInCache) {\n return _fullyQualifiedDomainNameInCache;\n }\n if (process.platform === \"win32\") {\n // http://serverfault.com/a/73643/251863\n const env = process.env;\n _fullyQualifiedDomainNameInCache =\n env.COMPUTERNAME + (env.USERDNSDOMAIN && env.USERDNSDOMAIN?.length > 0 ? `.${env.USERDNSDOMAIN as string}` : \"\");\n } else {\n try {\n _fullyQualifiedDomainNameInCache = await promisify(fqdn)();\n if (_fullyQualifiedDomainNameInCache === \"localhost\") {\n throw new Error(\"localhost not expected\");\n }\n if (/sethostname/.test(_fullyQualifiedDomainNameInCache as string)) {\n throw new Error(\"Detecting fqdn on windows !!!\");\n }\n } catch (_err) {\n // fall back to old method\n _fullyQualifiedDomainNameInCache = os.hostname();\n }\n }\n return _fullyQualifiedDomainNameInCache as string;\n}\n\nexport async function prepareFQDN() {\n _fullyQualifiedDomainNameInCache = await extractFullyQualifiedDomainName();\n}\n\nexport function getFullyQualifiedDomainName(optional_max_length?: number) {\n if (!_fullyQualifiedDomainNameInCache) {\n throw new Error(\"FullyQualifiedDomainName computation is not completed yet\");\n }\n return _fullyQualifiedDomainNameInCache ? trim(_fullyQualifiedDomainNameInCache, optional_max_length) : \"%FQDN%\";\n}\n\nexport function getHostname() {\n return os.hostname();\n}\n\nexport function resolveFullyQualifiedDomainName(str: string): string {\n if (!_fullyQualifiedDomainNameInCache) {\n throw new Error(\"FullyQualifiedDomainName computation is not completed yet\");\n }\n str = str.replace(\"%FQDN%\", _fullyQualifiedDomainNameInCache);\n str = str.replace(\"{FQDN}\", _fullyQualifiedDomainNameInCache);\n str = str.replace(\"{hostname}\", getHostname());\n return str;\n}\n// note : under windows ... echo %COMPUTERNAME%.%USERDNSDOMAIN%\nprepareFQDN();\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-shadowed-variable\n// tslint:disable:member-ordering\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { withLock } from \"@ster5/global-mutex\";\nimport chalk from \"chalk\";\nimport chokidar from \"chokidar\";\nimport {\n type Certificate,\n type CertificateInternals,\n type CertificateRevocationList,\n type CertificateRevocationListInfo,\n type DER,\n exploreCertificate,\n exploreCertificateInfo,\n exploreCertificateRevocationList,\n generatePrivateKeyFile,\n makeSHA1Thumbprint,\n readCertificate,\n readCertificateRevocationList,\n split_der,\n toPem,\n verifyCertificateSignature\n} from \"node-opcua-crypto\";\n\nimport type { SubjectOptions } from \"../misc/subject\";\nimport type {\n CertificateStatus,\n CreateSelfSignCertificateParam,\n CreateSelfSignCertificateWithConfigParam,\n Filename,\n KeySize,\n Thumbprint\n} from \"../toolbox/common\";\nimport { makePath, mkdirRecursiveSync } from \"../toolbox/common2\";\nimport { debugLog, warningLog } from \"../toolbox/debug\";\nimport { createCertificateSigningRequestAsync, createSelfSignedCertificate } from \"../toolbox/without_openssl\";\n\nimport _simple_config_template from \"./templates/simple_config_template.cnf\";\n\n/**\n *\n * a minimalist config file for openssl that allows\n * self-signed certificate to be generated.\n *\n */\n// tslint:disable-next-line:variable-name\nconst configurationFileSimpleTemplate: string = _simple_config_template;\nconst fsWriteFile = fs.promises.writeFile;\n\ninterface Entry {\n certificate: Certificate;\n filename: string;\n}\ninterface CRLEntry {\n crlInfo: CertificateRevocationListInfo;\n filename: string;\n}\ninterface CRLData {\n serialNumbers: { [key: string]: Date };\n crls: CRLEntry[];\n}\ninterface Thumbs {\n trusted: { [key: string]: Entry };\n rejected: { [key: string]: Entry };\n issuers: {\n certs: { [key: string]: Entry };\n };\n crl: {\n [key: string]: CRLData; // key is subjectFingerPrint of issuer Certificate\n };\n issuersCrl: {\n [key: string]: CRLData; // key is subjectFingerPrint of issuer Certificate\n };\n}\n\nexport interface CertificateManagerOptions {\n keySize?: KeySize;\n location: string;\n}\n\nexport interface CreateSelfSignCertificateParam1 extends CreateSelfSignCertificateParam {\n outputFile?: Filename; // default : own/cert/self_signed_certificate.pem\n subject: SubjectOptions | string;\n applicationUri: string;\n dns: string[];\n startDate: Date;\n validity: number;\n}\n\nexport interface VerifyCertificateOptions {\n acceptOutdatedCertificate?: boolean;\n acceptOutDatedIssuerCertificate?: boolean;\n ignoreMissingRevocationList?: boolean;\n acceptPendingCertificate?: boolean;\n // rejectSelfSignedCertificate: boolean;\n}\n\nexport enum VerificationStatus {\n /** The certificate provided as a parameter is not valid. */\n BadCertificateInvalid = \"BadCertificateInvalid\",\n /** An error occurred verifying security. */\n BadSecurityChecksFailed = \"BadSecurityChecksFailed\",\n /** The certificate does not meet the requirements of the security policy. */\n BadCertificatePolicyCheckFailed = \"BadCertificatePolicyCheckFailed\",\n /** The certificate has expired or is not yet valid. */\n BadCertificateTimeInvalid = \"BadCertificateTimeInvalid\",\n /** An issuer certificate has expired or is not yet valid. */\n BadCertificateIssuerTimeInvalid = \"BadCertificateIssuerTimeInvalid\",\n /** The HostName used to connect to a server does not match a HostName in the certificate. */\n BadCertificateHostNameInvalid = \"BadCertificateHostNameInvalid\",\n /** The URI specified in the ApplicationDescription does not match the URI in the certificate. */\n BadCertificateUriInvalid = \"BadCertificateUriInvalid\",\n /** The certificate may not be used for the requested operation. */\n BadCertificateUseNotAllowed = \"BadCertificateUseNotAllowed\",\n /** The issuer certificate may not be used for the requested operation. */\n BadCertificateIssuerUseNotAllowed = \"BadCertificateIssuerUseNotAllowed\",\n /** The certificate is not trusted. */\n BadCertificateUntrusted = \"BadCertificateUntrusted\",\n /** It was not possible to determine if the certificate has been revoked. */\n BadCertificateRevocationUnknown = \"BadCertificateRevocationUnknown\",\n /** It was not possible to determine if the issuer certificate has been revoked. */\n BadCertificateIssuerRevocationUnknown = \"BadCertificateIssuerRevocationUnknown\",\n /** The certificate has been revoked. */\n BadCertificateRevoked = \"BadCertificateRevoked\",\n /** The issuer certificate has been revoked. */\n BadCertificateIssuerRevoked = \"BadCertificateIssuerRevoked\",\n /** The certificate chain is incomplete. */\n BadCertificateChainIncomplete = \"BadCertificateChainIncomplete\",\n\n /** Validation OK. */\n Good = \"Good\"\n}\n\nfunction makeFingerprint(certificate: Certificate | CertificateRevocationList): string {\n return makeSHA1Thumbprint(certificate).toString(\"hex\");\n}\nfunction short(stringToShorten: string) {\n return stringToShorten.substring(0, 10);\n}\n// biome-ignore lint/suspicious/noControlCharactersInRegex: we need to filter control characters\nconst forbiddenChars = /[\\x00-\\x1F<>:\"/\\\\|?*]/g;\nfunction buildIdealCertificateName(certificate: Certificate): string {\n const fingerprint = makeFingerprint(certificate);\n try {\n const commonName = exploreCertificate(certificate).tbsCertificate.subject.commonName || \"\";\n // commonName may contain invalid characters for a filename such as / or \\ or :\n // that we need to replace with a valid character.\n // replace / or \\ or : with _\n const sanitizedCommonName = commonName.replace(forbiddenChars, \"_\");\n return `${sanitizedCommonName}[${fingerprint}]`;\n } catch (_err) {\n // make be certificate is incorrect !\n return `invalid_certificate_[${fingerprint}]`;\n }\n}\nfunction findMatchingIssuerKey(entries: Entry[], wantedIssuerKey: string): Entry[] {\n const selected = entries.filter(({ certificate }) => {\n const info = exploreCertificate(certificate);\n return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;\n });\n return selected;\n}\n\nfunction isSelfSigned2(info: CertificateInternals): boolean {\n return (\n info.tbsCertificate.extensions?.subjectKeyIdentifier ===\n info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier\n );\n}\n\nfunction isSelfSigned3(certificate: Buffer): boolean {\n const info = exploreCertificate(certificate);\n return isSelfSigned2(info);\n}\n\nexport function findIssuerCertificateInChain(certificate: Certificate, chain: Certificate[]): Certificate | null {\n if (!certificate) {\n return null;\n }\n const certInfo = exploreCertificate(certificate);\n\n // istanbul ignore next\n if (isSelfSigned2(certInfo)) {\n // the certificate is self signed so is it's own issuer.\n return certificate;\n }\n const wantedIssuerKey = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;\n\n // istanbul ignore next\n if (!wantedIssuerKey) {\n // Certificate has no extension 3 ! the certificate might have been generated by an old system\n debugLog(\"Certificate has no extension 3\");\n return null;\n }\n const potentialIssuers = chain.filter((c) => {\n const info = exploreCertificate(c);\n return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;\n });\n\n if (potentialIssuers.length === 1) {\n return potentialIssuers[0];\n }\n if (potentialIssuers.length > 1) {\n debugLog(\"findIssuerCertificateInChain: certificate is not self-signed but has several issuers\");\n return potentialIssuers[0];\n }\n return null;\n}\n\nexport enum CertificateManagerState {\n Uninitialized = 0,\n Initializing = 1,\n Initialized = 2,\n Disposing = 3,\n Disposed = 4\n}\nexport class CertificateManager {\n public untrustUnknownCertificate = true;\n public state: CertificateManagerState = CertificateManagerState.Uninitialized;\n public folderPoolingInterval = 5000;\n\n public readonly keySize: KeySize;\n private readonly location: string;\n private readonly _watchers: fs.FSWatcher[] = [];\n private _readCertificatesCalled = false;\n private readonly _filenameToHash: { [key: string]: string } = {};\n\n private readonly _thumbs: Thumbs = {\n rejected: {},\n trusted: {},\n issuers: {\n certs: {}\n },\n crl: {},\n issuersCrl: {}\n };\n\n constructor(options: CertificateManagerOptions) {\n options.keySize = options.keySize || 2048;\n assert(Object.prototype.hasOwnProperty.call(options, \"location\"));\n assert(Object.prototype.hasOwnProperty.call(options, \"keySize\"));\n assert(this.state === CertificateManagerState.Uninitialized);\n\n this.location = makePath(options.location, \"\");\n this.keySize = options.keySize;\n\n mkdirRecursiveSync(options.location);\n\n // istanbul ignore next\n if (!fs.existsSync(this.location)) {\n throw new Error(`CertificateManager cannot access location ${this.location}`);\n }\n }\n\n get configFile() {\n return path.join(this.rootDir, \"own/openssl.cnf\");\n }\n\n get rootDir() {\n return this.location;\n }\n\n get privateKey() {\n return path.join(this.rootDir, \"own/private/private_key.pem\");\n }\n\n get randomFile() {\n return path.join(this.rootDir, \"./random.rnd\");\n }\n\n /**\n * returns the certificate status trusted/rejected\n * @param certificate\n */\n public async getCertificateStatus(certificate: Buffer): Promise<CertificateStatus> {\n await this.initialize();\n let status = await this._checkRejectedOrTrusted(certificate);\n if (status === \"unknown\") {\n assert(certificate instanceof Buffer);\n\n const pem = toPem(certificate, \"CERTIFICATE\");\n const fingerprint = makeFingerprint(certificate);\n const filename = path.join(this.rejectedFolder, `${buildIdealCertificateName(certificate)}.pem`);\n await fs.promises.writeFile(filename, pem);\n this._thumbs.rejected[fingerprint] = {\n certificate,\n filename\n };\n status = \"rejected\";\n }\n return status;\n }\n\n /**\n * Move a certificate to the rejected store.\n * If the certificate was previously trusted, it will be moved.\n * @param certificate - the DER-encoded certificate\n */\n public async rejectCertificate(certificate: Certificate): Promise<void> {\n await this._moveCertificate(certificate, \"rejected\");\n }\n\n /**\n * Move a certificate to the trusted store.\n * If the certificate was previously rejected, it will be moved.\n * @param certificate - the DER-encoded certificate\n */\n public async trustCertificate(certificate: Certificate): Promise<void> {\n await this._moveCertificate(certificate, \"trusted\");\n }\n\n /** Path to the rejected certificates folder. */\n public get rejectedFolder(): string {\n return path.join(this.rootDir, \"rejected\");\n }\n /** Path to the trusted certificates folder. */\n public get trustedFolder(): string {\n return path.join(this.rootDir, \"trusted/certs\");\n }\n /** Path to the trusted CRL folder. */\n public get crlFolder(): string {\n return path.join(this.rootDir, \"trusted/crl\");\n }\n /** Path to the issuer (CA) certificates folder. */\n public get issuersCertFolder(): string {\n return path.join(this.rootDir, \"issuers/certs\");\n }\n /** Path to the issuer CRL folder. */\n public get issuersCrlFolder(): string {\n return path.join(this.rootDir, \"issuers/crl\");\n }\n\n /**\n * Check if a certificate is in the trusted store.\n * If the certificate is unknown and `untrustUnknownCertificate` is set,\n * it will be written to the rejected folder.\n * @param certificate - the DER-encoded certificate\n * @returns `\"Good\"` if trusted, `\"BadCertificateUntrusted\"` if rejected/unknown,\n * or `\"BadCertificateInvalid\"` if the certificate cannot be parsed.\n */\n public async isCertificateTrusted(certificate: Certificate): Promise<string> {\n const fingerprint = makeFingerprint(certificate) as Thumbprint;\n const certificateInTrust = this._thumbs.trusted[fingerprint]?.certificate;\n\n if (certificateInTrust) {\n return \"Good\";\n } else {\n const certificateInRejected = this._thumbs.rejected[fingerprint];\n if (!certificateInRejected) {\n const certificateFilenameInRejected = path.join(\n this.rejectedFolder,\n `${buildIdealCertificateName(certificate)}.pem`\n );\n if (!this.untrustUnknownCertificate) {\n return \"Good\";\n }\n // Certificate should be mark as untrusted\n // let's first verify that certificate is valid ,as we don't want to write invalid data\n try {\n const _certificateInfo = exploreCertificateInfo(certificate);\n _certificateInfo;\n } catch (_err) {\n return \"BadCertificateInvalid\";\n }\n debugLog(\"certificate has never been seen before and is now rejected (untrusted) \", certificateFilenameInRejected);\n await fsWriteFile(certificateFilenameInRejected, toPem(certificate, \"CERTIFICATE\"));\n }\n return \"BadCertificateUntrusted\";\n }\n }\n public async _innerVerifyCertificateAsync(\n certificate: Certificate,\n _isIssuer: boolean,\n level: number,\n options: VerifyCertificateOptions\n ): Promise<VerificationStatus> {\n if (level >= 5) {\n // maximum level of certificate in chain reached !\n return VerificationStatus.BadSecurityChecksFailed;\n }\n const chain = split_der(certificate);\n debugLog(\"NB CERTIFICATE IN CHAIN = \", chain.length);\n const info = exploreCertificate(chain[0]);\n\n let hasValidIssuer = false;\n let hasTrustedIssuer = false;\n // check if certificate is attached to a issuer\n const hasIssuerKey = info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;\n debugLog(\"Certificate as an Issuer Key\", hasIssuerKey);\n\n if (hasIssuerKey) {\n const isSelfSigned = isSelfSigned2(info);\n\n debugLog(\"Is the Certificate self-signed ?\", isSelfSigned);\n if (!isSelfSigned) {\n debugLog(\n \"Is issuer found in the list of know issuers ?\",\n \"\\n subjectKeyIdentifier = \",\n info.tbsCertificate.extensions?.subjectKeyIdentifier,\n \"\\n authorityKeyIdentifier = \",\n info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier\n );\n let issuerCertificate = await this.findIssuerCertificate(chain[0]);\n if (!issuerCertificate) {\n // the issuer has not been found in the list of trusted certificate\n // may be the issuer certificate is in the chain itself ?\n issuerCertificate = findIssuerCertificateInChain(chain[0], chain);\n if (!issuerCertificate) {\n debugLog(\n \" the issuer has not been found in the chain itself nor in the issuer.cert list => the chain is incomplete!\"\n );\n return VerificationStatus.BadCertificateChainIncomplete;\n }\n debugLog(\" the issuer certificate has been found in the chain itself ! the chain is complete !\");\n } else {\n debugLog(\" the issuer certificate has been found in the issuer.cert folder !\");\n }\n const issuerStatus = await this._innerVerifyCertificateAsync(issuerCertificate, true, level + 1, options);\n if (issuerStatus === VerificationStatus.BadCertificateRevocationUnknown) {\n // the issuer must have a CRL available .... !\n return VerificationStatus.BadCertificateIssuerRevocationUnknown;\n }\n if (issuerStatus === VerificationStatus.BadCertificateIssuerRevocationUnknown) {\n // the issuer must have a CRL available .... !\n return VerificationStatus.BadCertificateIssuerRevocationUnknown;\n }\n if (issuerStatus === VerificationStatus.BadCertificateTimeInvalid) {\n if (!options || !options.acceptOutDatedIssuerCertificate) {\n // the issuer must have valid dates ....\n return VerificationStatus.BadCertificateIssuerTimeInvalid;\n }\n }\n if (issuerStatus === VerificationStatus.BadCertificateUntrusted) {\n debugLog(\"warning issuerStatus = \", issuerStatus.toString(), \"the issuer certificate is not trusted\");\n // return VerificationStatus.BadSecurityChecksFailed;\n }\n\n if (issuerStatus !== VerificationStatus.Good && issuerStatus !== VerificationStatus.BadCertificateUntrusted) {\n // if the issuer has other issue => let's drop!\n return VerificationStatus.BadSecurityChecksFailed;\n }\n // verify that certificate was signed by issuer\n const isCertificateSignatureOK = verifyCertificateSignature(certificate, issuerCertificate);\n if (!isCertificateSignatureOK) {\n debugLog(\" the certificate was not signed by the issuer as it claim to be ! Danger\");\n return VerificationStatus.BadSecurityChecksFailed;\n }\n hasValidIssuer = true;\n\n // let detected if our certificate is in the revocation list\n let revokedStatus = await this.isCertificateRevoked(certificate);\n if (revokedStatus === VerificationStatus.BadCertificateRevocationUnknown) {\n if (options?.ignoreMissingRevocationList) {\n // continue as if the certificate was not revoked\n revokedStatus = VerificationStatus.Good;\n }\n }\n if (revokedStatus !== VerificationStatus.Good) {\n // certificate is revoked !!!\n debugLog(\"revokedStatus\", revokedStatus);\n return revokedStatus;\n }\n\n // let check if the issuer is explicitly trusted\n const issuerTrustedStatus = await this._checkRejectedOrTrusted(issuerCertificate);\n debugLog(\"issuerTrustedStatus\", issuerTrustedStatus);\n\n if (issuerTrustedStatus === \"unknown\") {\n hasTrustedIssuer = false;\n } else if (issuerTrustedStatus === \"trusted\") {\n hasTrustedIssuer = true;\n } else if (issuerTrustedStatus === \"rejected\") {\n // we should never get there: this should have been detected before !!!\n return VerificationStatus.BadSecurityChecksFailed;\n }\n } else {\n // verify that certificate was signed by issuer (self in this case)\n const isCertificateSignatureOK = verifyCertificateSignature(certificate, certificate);\n if (!isCertificateSignatureOK) {\n debugLog(\"Self-signed Certificate signature is not valid\");\n return VerificationStatus.BadSecurityChecksFailed;\n }\n const revokedStatus = await this.isCertificateRevoked(certificate);\n debugLog(\"revokedStatus of self signed certificate:\", revokedStatus);\n }\n }\n\n const status = await this._checkRejectedOrTrusted(certificate);\n if (status === \"rejected\") {\n return VerificationStatus.BadCertificateUntrusted;\n }\n\n const _c2 = chain[1] ? exploreCertificateInfo(chain[1]) : \"non\";\n _c2;\n\n // Has SoftwareCertificate passed its issue date and has it not expired ?\n // check dates\n const certificateInfo = exploreCertificateInfo(certificate);\n const now = new Date();\n\n let isTimeInvalid = false;\n // check that certificate is active\n if (certificateInfo.notBefore.getTime() > now.getTime()) {\n // certificate is not active yet\n debugLog(\n chalk.red(\"certificate is invalid : certificate is not active yet !\") +\n \" not before date =\" +\n certificateInfo.notBefore\n );\n if (!options.acceptPendingCertificate) {\n isTimeInvalid = true;\n }\n }\n\n // check that certificate has not expired\n if (certificateInfo.notAfter.getTime() <= now.getTime()) {\n // certificate is obsolete\n debugLog(\n `${chalk.red(\"certificate is invalid : certificate has expired !\")} not after date =${certificateInfo.notAfter}`\n );\n if (!options.acceptOutdatedCertificate) {\n isTimeInvalid = true;\n }\n }\n if (status === \"trusted\") {\n return isTimeInvalid ? VerificationStatus.BadCertificateTimeInvalid : VerificationStatus.Good;\n }\n assert(status === \"unknown\");\n if (hasIssuerKey) {\n if (!hasTrustedIssuer) {\n return VerificationStatus.BadCertificateUntrusted;\n }\n if (!hasValidIssuer) {\n return VerificationStatus.BadCertificateUntrusted;\n }\n return isTimeInvalid ? VerificationStatus.BadCertificateTimeInvalid : VerificationStatus.Good;\n } else {\n return VerificationStatus.BadCertificateUntrusted;\n }\n }\n\n protected async verifyCertificateAsync(\n certificate: Certificate,\n options: VerifyCertificateOptions\n ): Promise<VerificationStatus> {\n const status1 = await this._innerVerifyCertificateAsync(certificate, false, 0, options);\n return status1;\n }\n\n /**\n * Verify certificate validity\n * @method verifyCertificate\n * @param certificate\n */\n public async verifyCertificate(certificate: Certificate, options?: VerifyCertificateOptions): Promise<VerificationStatus> {\n // Is the signature on the SoftwareCertificate valid .?\n if (!certificate) {\n // missing certificate\n return VerificationStatus.BadSecurityChecksFailed;\n }\n return await this.verifyCertificateAsync(certificate, options || {});\n }\n\n /*\n *\n * PKI\n * +---> trusted\n * +---> rejected\n * +---> own\n * +---> cert\n * +---> own\n *\n */\n public async initialize(): Promise<void> {\n if (this.state !== CertificateManagerState.Uninitialized) {\n return;\n }\n this.state = CertificateManagerState.Initializing;\n await this._initialize();\n this.state = CertificateManagerState.Initialized;\n }\n private async _initialize(): Promise<void> {\n this.state = CertificateManagerState.Initializing;\n const pkiDir = this.location;\n mkdirRecursiveSync(pkiDir);\n mkdirRecursiveSync(path.join(pkiDir, \"own\"));\n mkdirRecursiveSync(path.join(pkiDir, \"own/certs\"));\n mkdirRecursiveSync(path.join(pkiDir, \"own/private\"));\n mkdirRecursiveSync(path.join(pkiDir, \"rejected\"));\n mkdirRecursiveSync(path.join(pkiDir, \"trusted\"));\n mkdirRecursiveSync(path.join(pkiDir, \"trusted/certs\"));\n mkdirRecursiveSync(path.join(pkiDir, \"trusted/crl\"));\n\n mkdirRecursiveSync(path.join(pkiDir, \"issuers\"));\n mkdirRecursiveSync(path.join(pkiDir, \"issuers/certs\")); // contains Trusted CA certificates\n mkdirRecursiveSync(path.join(pkiDir, \"issuers/crl\")); // contains CRL of revoked CA certificates\n\n if (!fs.existsSync(this.configFile) || !fs.existsSync(this.privateKey)) {\n return await this.withLock2(async () => {\n assert(this.state !== CertificateManagerState.Disposing);\n if (this.state === CertificateManagerState.Disposed) {\n return;\n }\n assert(this.state === CertificateManagerState.Initializing);\n\n if (!fs.existsSync(this.configFile)) {\n fs.writeFileSync(this.configFile, configurationFileSimpleTemplate);\n }\n // note : openssl 1.1.1 has a bug that causes a failure if\n // random file cannot be found. (should be fixed in 1.1.1.a)\n // if this issue become important we may have to consider checking that rndFile exists and recreate\n // it if not . this could be achieved with the command :\n // \"openssl rand -writerand ${this.randomFile}\"\n //\n // cf: https://github.com/node-opcua/node-opcua/issues/554\n\n if (!fs.existsSync(this.privateKey)) {\n debugLog(\"generating private key ...\");\n // setEnv(\"RANDFILE\", this.randomFile);\n await generatePrivateKeyFile(this.privateKey, this.keySize);\n await this._readCertificates();\n } else {\n // debugLog(\" initialize : private key already exists ... skipping\");\n await this._readCertificates();\n }\n });\n } else {\n await this._readCertificates();\n }\n }\n\n /**\n * Dispose of the CertificateManager, releasing file watchers\n * and other resources. The instance should not be used after\n * calling this method.\n */\n public async dispose(): Promise<void> {\n if (this.state === CertificateManagerState.Disposing) {\n throw new Error(\"Already disposing\");\n }\n\n if (this.state === CertificateManagerState.Uninitialized) {\n this.state = CertificateManagerState.Disposed;\n return;\n }\n\n // wait for initialization to be completed\n if (this.state === CertificateManagerState.Initializing) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n return await this.dispose();\n }\n\n try {\n this.state = CertificateManagerState.Disposing;\n await Promise.all(this._watchers.map((w) => w.close()));\n this._watchers.forEach((w) => {\n w.removeAllListeners();\n });\n this._watchers.splice(0);\n } finally {\n this.state = CertificateManagerState.Disposed;\n }\n }\n\n protected async withLock2<T>(action: () => Promise<T>): Promise<T> {\n const lockFileName = path.join(this.rootDir, \"mutex.lock\");\n return withLock<T>({ fileToLock: lockFileName }, async () => {\n return await action();\n });\n }\n /**\n *\n * create a self-signed certificate for the CertificateManager private key\n *\n */\n public async createSelfSignedCertificate(params: CreateSelfSignCertificateParam1): Promise<void> {\n assert(typeof params.applicationUri === \"string\", \"expecting applicationUri\");\n if (!fs.existsSync(this.privateKey)) {\n throw new Error(`Cannot find private key ${this.privateKey}`);\n }\n\n let certificateFilename = path.join(this.rootDir, \"own/certs/self_signed_certificate.pem\");\n certificateFilename = params.outputFile || certificateFilename;\n\n const _params = params as unknown as CreateSelfSignCertificateWithConfigParam;\n _params.rootDir = this.rootDir;\n _params.configFile = this.configFile;\n _params.privateKey = this.privateKey;\n\n _params.subject = params.subject || \"CN=FIXME\";\n await this.withLock2(async () => {\n await createSelfSignedCertificate(certificateFilename, _params);\n });\n }\n\n public async createCertificateRequest(params: CreateSelfSignCertificateParam): Promise<Filename> {\n assert(params);\n const _params = params as CreateSelfSignCertificateWithConfigParam;\n if (Object.prototype.hasOwnProperty.call(_params, \"rootDir\")) {\n throw new Error(\"rootDir should not be specified \");\n }\n assert(!_params.rootDir);\n assert(!_params.configFile);\n assert(!_params.privateKey);\n _params.rootDir = path.resolve(this.rootDir);\n _params.configFile = path.resolve(this.configFile);\n _params.privateKey = path.resolve(this.privateKey);\n\n return await this.withLock2<string>(async () => {\n // compose a file name for the request\n const now = new Date();\n const today = `${now.toISOString().slice(0, 10)}_${now.getTime()}`;\n const certificateSigningRequestFilename = path.join(this.rootDir, \"own/certs\", `certificate_${today}.csr`);\n await createCertificateSigningRequestAsync(certificateSigningRequestFilename, _params);\n return certificateSigningRequestFilename;\n });\n }\n\n /**\n * Add a CA (issuer) certificate to the issuers store.\n * If the certificate is already present, this is a no-op.\n * @param certificate - the DER-encoded CA certificate\n * @param validate - if `true`, verify the certificate before adding\n * @param addInTrustList - if `true`, also add to the trusted store\n * @returns `VerificationStatus.Good` on success\n */\n public async addIssuer(certificate: DER, validate = false, addInTrustList = false): Promise<VerificationStatus> {\n if (validate) {\n const status = await this.verifyCertificate(certificate);\n if (status !== VerificationStatus.Good && status !== VerificationStatus.BadCertificateUntrusted) {\n return status;\n }\n }\n const pemCertificate = toPem(certificate, \"CERTIFICATE\");\n const fingerprint = makeFingerprint(certificate);\n if (this._thumbs.issuers.certs[fingerprint]) {\n // already in .. simply ignore\n return VerificationStatus.Good;\n }\n // write certificate\n const filename = path.join(this.issuersCertFolder, `issuer_${buildIdealCertificateName(certificate)}.pem`);\n await fs.promises.writeFile(filename, pemCertificate, \"ascii\");\n\n // first time seen, let's save it.\n this._thumbs.issuers.certs[fingerprint] = { certificate, filename };\n\n if (addInTrustList) {\n // add certificate in the trust list as well\n await this.trustCertificate(certificate);\n }\n\n return VerificationStatus.Good;\n }\n\n /**\n * Add a CRL to the certificate manager.\n * @param crl - the CRL to add\n * @param target - \"issuers\" (default) writes to issuers/crl, \"trusted\" writes to trusted/crl\n */\n public async addRevocationList(\n crl: CertificateRevocationList,\n target: \"issuers\" | \"trusted\" = \"issuers\"\n ): Promise<VerificationStatus> {\n return await this.withLock2<VerificationStatus>(async () => {\n try {\n const index = target === \"trusted\" ? this._thumbs.crl : this._thumbs.issuersCrl;\n const folder = target === \"trusted\" ? this.crlFolder : this.issuersCrlFolder;\n\n const crlInfo = exploreCertificateRevocationList(crl);\n const key = crlInfo.tbsCertList.issuerFingerprint;\n if (!index[key]) {\n index[key] = { crls: [], serialNumbers: {} };\n }\n const pemCertificate = toPem(crl, \"X509 CRL\");\n const filename = path.join(folder, `crl_${buildIdealCertificateName(crl)}.pem`);\n await fs.promises.writeFile(filename, pemCertificate, \"ascii\");\n\n await this._on_crl_file_added(index, filename);\n\n await this.waitAndCheckCRLProcessingStatus();\n\n return VerificationStatus.Good;\n } catch (err) {\n debugLog(err);\n return VerificationStatus.BadSecurityChecksFailed;\n }\n });\n }\n\n /**\n * Remove all CRL files from the specified folder(s) and clear the\n * corresponding in-memory index.\n * @param target - \"issuers\" clears issuers/crl, \"trusted\" clears\n * trusted/crl, \"all\" clears both.\n */\n public async clearRevocationLists(target: \"issuers\" | \"trusted\" | \"all\"): Promise<void> {\n const clearFolder = async (folder: string, index: { [key: string]: CRLData }) => {\n try {\n const files = await fs.promises.readdir(folder);\n for (const file of files) {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".crl\" || ext === \".pem\" || ext === \".der\") {\n await fs.promises.unlink(path.join(folder, file));\n }\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n // Clear the in-memory index\n for (const key of Object.keys(index)) {\n delete index[key];\n }\n };\n\n if (target === \"issuers\" || target === \"all\") {\n await clearFolder(this.issuersCrlFolder, this._thumbs.issuersCrl);\n }\n if (target === \"trusted\" || target === \"all\") {\n await clearFolder(this.crlFolder, this._thumbs.crl);\n }\n }\n\n /**\n * Check whether an issuer certificate with the given thumbprint\n * is already registered.\n * @param thumbprint - hex-encoded SHA-1 thumbprint (lowercase)\n */\n public async hasIssuer(thumbprint: string): Promise<boolean> {\n await this._readCertificates();\n const normalized = thumbprint.toLowerCase();\n return Object.prototype.hasOwnProperty.call(this._thumbs.issuers.certs, normalized);\n }\n\n /**\n * Remove a trusted certificate identified by its SHA-1 thumbprint.\n * Deletes the file on disk and removes the entry from the\n * in-memory index.\n * @param thumbprint - hex-encoded SHA-1 thumbprint (lowercase)\n * @returns the removed certificate buffer, or `null` if not found\n */\n public async removeTrustedCertificate(thumbprint: string): Promise<Certificate | null> {\n await this._readCertificates();\n const normalized = thumbprint.toLowerCase();\n const entry = this._thumbs.trusted[normalized];\n if (!entry) {\n return null;\n }\n try {\n await fs.promises.unlink(entry.filename);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n delete this._thumbs.trusted[normalized];\n return entry.certificate;\n }\n\n /**\n * Remove an issuer certificate identified by its SHA-1 thumbprint.\n * Deletes the file on disk and removes the entry from the\n * in-memory index.\n * @param thumbprint - hex-encoded SHA-1 thumbprint (lowercase)\n * @returns the removed certificate buffer, or `null` if not found\n */\n public async removeIssuer(thumbprint: string): Promise<Certificate | null> {\n await this._readCertificates();\n const normalized = thumbprint.toLowerCase();\n const entry = this._thumbs.issuers.certs[normalized];\n if (!entry) {\n return null;\n }\n try {\n await fs.promises.unlink(entry.filename);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n delete this._thumbs.issuers.certs[normalized];\n return entry.certificate;\n }\n\n /**\n * Remove all CRL files that were issued by the given CA certificate\n * from the specified folder (or both).\n * @param issuerCertificate - the CA certificate whose CRLs to remove\n * @param target - \"issuers\", \"trusted\", or \"all\" (default \"all\")\n */\n public async removeRevocationListsForIssuer(\n issuerCertificate: Certificate,\n target: \"issuers\" | \"trusted\" | \"all\" = \"all\"\n ): Promise<void> {\n const issuerInfo = exploreCertificate(issuerCertificate);\n const issuerFingerprint = issuerInfo.tbsCertificate.subjectFingerPrint;\n\n const processIndex = async (index: { [key: string]: CRLData }) => {\n const crlData = index[issuerFingerprint];\n if (!crlData) return;\n for (const crlEntry of crlData.crls) {\n try {\n await fs.promises.unlink(crlEntry.filename);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n }\n delete index[issuerFingerprint];\n };\n\n if (target === \"issuers\" || target === \"all\") {\n await processIndex(this._thumbs.issuersCrl);\n }\n if (target === \"trusted\" || target === \"all\") {\n await processIndex(this._thumbs.crl);\n }\n }\n\n /**\n * Validate a certificate (optionally with its chain) and add\n * the leaf certificate to the trusted store.\n *\n * The certificate buffer may contain a single certificate or a\n * full chain (leaf + issuer certificates concatenated in DER).\n * Only the leaf certificate is added to the trusted store.\n *\n * When the chain contains issuer certificates, this method\n * verifies that each issuer is already registered via\n * {@link addIssuer} before trusting the leaf.\n *\n * @param certificateChain - DER-encoded certificate or chain\n * @returns `VerificationStatus.Good` on success, or an error\n * status indicating why the certificate was rejected.\n */\n public async addTrustedCertificateFromChain(certificateChain: Certificate): Promise<VerificationStatus> {\n const certificates = split_der(certificateChain);\n const leafCertificate = certificates[0];\n\n // Structural validation — can we parse it?\n try {\n exploreCertificate(leafCertificate);\n } catch (_err) {\n return VerificationStatus.BadCertificateInvalid;\n }\n\n // Full chain validation using this CertificateManager's\n // trust store, issuer store, and CRL data\n const status = await this.verifyCertificate(leafCertificate, {\n ignoreMissingRevocationList: true\n });\n if (status !== VerificationStatus.Good && status !== VerificationStatus.BadCertificateUntrusted) {\n return status;\n }\n\n // If a chain was provided, verify that every issuer in the\n // chain is already registered in the issuers store\n if (certificates.length > 1) {\n for (const issuerCert of certificates.slice(1)) {\n const thumbprint = makeFingerprint(issuerCert);\n if (!Object.prototype.hasOwnProperty.call(this._thumbs.issuers.certs, thumbprint)) {\n return VerificationStatus.BadCertificateChainIncomplete;\n }\n }\n }\n\n // All checks passed — trust the leaf certificate\n await this.trustCertificate(leafCertificate);\n return VerificationStatus.Good;\n }\n\n /**\n * Check whether an issuer certificate is still needed by any\n * certificate in the trusted store.\n *\n * This is used before removing an issuer to ensure that\n * doing so would not break the chain of any trusted\n * certificate.\n *\n * @param issuerCertificate - the CA certificate to check\n * @returns `true` if at least one trusted certificate was\n * signed by this issuer.\n */\n public async isIssuerInUseByTrustedCertificate(issuerCertificate: Certificate): Promise<boolean> {\n await this._readCertificates();\n for (const entry of Object.values(this._thumbs.trusted)) {\n if (!entry.certificate) continue;\n try {\n if (verifyCertificateSignature(entry.certificate, issuerCertificate)) {\n return true;\n }\n } catch (_err) {\n // Skip certificates that can't be verified\n }\n }\n return false;\n }\n\n /**\n * find the issuer certificate among the trusted issuer certificates.\n *\n * The findIssuerCertificate method is an asynchronous method that attempts to find\n * the issuer certificate for a given certificate from the list of issuer certificate declared in the PKI\n *\n * - If the certificate is self-signed, it returns the certificate itself.\n *\n * - If the certificate has no extension 3, it is assumed to be generated by an old system, and a null value is returned.\n *\n * - the method checks both issuer and trusted certificates and returns the appropriate issuercertificate,\n * if found. If multiple matching certificates are found, a warning is logged to the console.\n *\n */\n public async findIssuerCertificate(certificate: Certificate): Promise<Certificate | null> {\n const certInfo = exploreCertificate(certificate);\n\n // istanbul ignore next\n if (isSelfSigned2(certInfo)) {\n // the certificate is self signed so is it's own issuer.\n return certificate;\n }\n\n const wantedIssuerKey = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;\n\n // istanbul ignore next\n if (!wantedIssuerKey) {\n // Certificate has no extension 3 ! the certificate might have been generated by an old system\n debugLog(\"Certificate has no extension 3\");\n return null;\n }\n\n const issuerCertificates = Object.values(this._thumbs.issuers.certs);\n\n const selectedIssuerCertificates = findMatchingIssuerKey(issuerCertificates, wantedIssuerKey);\n\n if (selectedIssuerCertificates.length > 0) {\n if (selectedIssuerCertificates.length > 1) {\n // tslint:disable-next-line: no-console\n warningLog(\"Warning more than one issuer certificate exists with subjectKeyIdentifier \", wantedIssuerKey);\n }\n return selectedIssuerCertificates[0].certificate || null;\n }\n // check also in trusted list\n const trustedCertificates = Object.values(this._thumbs.trusted);\n const selectedTrustedCertificates = findMatchingIssuerKey(trustedCertificates, wantedIssuerKey);\n\n // istanbul ignore next\n if (selectedTrustedCertificates.length > 1) {\n // tslint:disable-next-line: no-console\n warningLog(\n \"Warning more than one certificate exists with subjectKeyIdentifier in trusted certificate list \",\n wantedIssuerKey,\n selectedTrustedCertificates.length\n );\n }\n return selectedTrustedCertificates.length > 0 ? selectedTrustedCertificates[0].certificate : null;\n }\n\n /**\n * @internal\n * @private\n */\n public async _checkRejectedOrTrusted(certificate: Buffer): Promise<CertificateStatus> {\n assert(certificate instanceof Buffer);\n const fingerprint = makeFingerprint(certificate);\n\n debugLog(\"_checkRejectedOrTrusted fingerprint \", short(fingerprint));\n\n await this._readCertificates();\n\n if (Object.prototype.hasOwnProperty.call(this._thumbs.rejected, fingerprint)) {\n return \"rejected\";\n }\n if (Object.prototype.hasOwnProperty.call(this._thumbs.trusted, fingerprint)) {\n return \"trusted\";\n }\n return \"unknown\";\n }\n\n private async _moveCertificate(certificate: Certificate, newStatus: CertificateStatus) {\n // a mutex is requested here\n\n assert(certificate instanceof Buffer);\n const fingerprint = makeFingerprint(certificate);\n\n const status = await this.getCertificateStatus(certificate);\n debugLog(\"_moveCertificate\", fingerprint.substring(0, 10), \"from\", status, \"to\", newStatus);\n assert(status === \"rejected\" || status === \"trusted\");\n\n if (status !== newStatus) {\n const indexSrc = status === \"rejected\" ? this._thumbs.rejected : this._thumbs.trusted;\n const certificateSrc = indexSrc[fingerprint]?.filename;\n\n // istanbul ignore next\n if (!certificateSrc) {\n debugLog(\" cannot find certificate \", fingerprint.substring(0, 10), \" in\", this._thumbs, [status]);\n throw new Error(\"internal\");\n }\n const destFolder =\n newStatus === \"rejected\" ? this.rejectedFolder : newStatus === \"trusted\" ? this.trustedFolder : this.rejectedFolder;\n const certificateDest = path.join(destFolder, path.basename(certificateSrc));\n\n debugLog(\"_moveCertificate1\", fingerprint.substring(0, 10), \"old name\", certificateSrc);\n debugLog(\"_moveCertificate1\", fingerprint.substring(0, 10), \"new name\", certificateDest);\n await fs.promises.rename(certificateSrc, certificateDest);\n delete indexSrc[fingerprint];\n const indexDest =\n newStatus === \"rejected\"\n ? this._thumbs.rejected\n : newStatus === \"trusted\"\n ? this._thumbs.trusted\n : this._thumbs.rejected;\n indexDest[fingerprint] = {\n certificate,\n filename: certificateDest\n };\n }\n }\n private _findAssociatedCRLs(issuerCertificate: Certificate): CRLData | null {\n const issuerCertificateInfo = exploreCertificate(issuerCertificate);\n const key = issuerCertificateInfo.tbsCertificate.subjectFingerPrint;\n return this._thumbs.issuersCrl[key] ? this._thumbs.issuersCrl[key] : this._thumbs.crl[key] ? this._thumbs.crl[key] : null;\n }\n\n public async isCertificateRevoked(\n certificate: Certificate,\n issuerCertificate?: Certificate | null\n ): Promise<VerificationStatus> {\n // istanbul ignore next\n if (isSelfSigned3(certificate)) {\n return VerificationStatus.Good;\n }\n\n if (!issuerCertificate) {\n issuerCertificate = await this.findIssuerCertificate(certificate);\n }\n if (!issuerCertificate) {\n return VerificationStatus.BadCertificateChainIncomplete;\n }\n const crls = this._findAssociatedCRLs(issuerCertificate);\n\n if (!crls) {\n return VerificationStatus.BadCertificateRevocationUnknown;\n }\n const certInfo = exploreCertificate(certificate);\n const serialNumber =\n certInfo.tbsCertificate.serialNumber || certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.serial || \"\";\n\n const key = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.authorityCertIssuerFingerPrint || \"<unknown>\";\n const crl2 = this._thumbs.crl[key] || null;\n\n if (crls.serialNumbers[serialNumber] || crl2?.serialNumbers[serialNumber]) {\n return VerificationStatus.BadCertificateRevoked;\n }\n return VerificationStatus.Good;\n }\n\n private _pending_crl_to_process = 0;\n private _on_crl_process?: () => void;\n private queue: { index: { [key: string]: CRLData }; filename: string }[] = [];\n private _on_crl_file_added(index: { [key: string]: CRLData }, filename: string) {\n this.queue.push({ index, filename });\n this._pending_crl_to_process += 1;\n if (this._pending_crl_to_process === 1) {\n this._process_next_crl();\n }\n }\n private async _process_next_crl() {\n try {\n const nextCRL = this.queue.shift();\n if (!nextCRL) return;\n const { index, filename } = nextCRL;\n const crl = await readCertificateRevocationList(filename);\n const crlInfo = exploreCertificateRevocationList(crl);\n debugLog(chalk.cyan(\"add CRL in folder \"), filename); // stat);\n const fingerprint = crlInfo.tbsCertList.issuerFingerprint;\n index[fingerprint] = index[fingerprint] || {\n crls: [],\n serialNumbers: {}\n };\n index[fingerprint].crls.push({ crlInfo, filename });\n\n const serialNumbers = index[fingerprint].serialNumbers;\n // now inject serial numbers\n for (const revokedCertificate of crlInfo.tbsCertList.revokedCertificates) {\n const serialNumber = revokedCertificate.userCertificate;\n if (!serialNumbers[serialNumber]) {\n serialNumbers[serialNumber] = revokedCertificate.revocationDate;\n }\n }\n debugLog(chalk.cyan(\"CRL\"), fingerprint, \"serial numbers = \", Object.keys(serialNumbers)); // stat);\n } catch (err) {\n debugLog(\"CRL filename error =\");\n debugLog(err);\n }\n this._pending_crl_to_process -= 1;\n if (this._pending_crl_to_process === 0) {\n if (this._on_crl_process) {\n this._on_crl_process();\n this._on_crl_process = undefined;\n }\n } else {\n this._process_next_crl();\n }\n }\n private async _readCertificates(): Promise<void> {\n if (this._readCertificatesCalled) {\n return;\n }\n this._readCertificatesCalled = true;\n\n const options = {\n usePolling: true,\n interval: Math.min(10 * 60 * 1000, Math.max(100, this.folderPoolingInterval)),\n persistent: false,\n awaitWriteFinish: {\n stabilityThreshold: 2000,\n pollInterval: 600\n }\n };\n async function _walkCRLFiles(this: CertificateManager, folder: string, index: { [key: string]: CRLData }) {\n await new Promise<void>((resolve, _reject) => {\n const w = chokidar.watch(folder, options);\n\n w.on(\"unlink\", (filename: string, stat?: fs.Stats) => {\n filename;\n stat;\n // CRL never removed\n });\n w.on(\"add\", (filename: string, stat?: fs.Stats) => {\n stat;\n this._on_crl_file_added(index, filename);\n });\n w.on(\"change\", (path: string, stat?: fs.Stats) => {\n debugLog(\"change in folder \", folder, path, stat);\n });\n this._watchers.push(w as unknown as fs.FSWatcher);\n w.on(\"ready\", () => {\n resolve();\n });\n });\n }\n\n async function _walkAllFiles(this: CertificateManager, folder: string, index: { [key: string]: Entry }) {\n const w = chokidar.watch(folder, options);\n w.on(\"unlink\", (filename: string, stat?: fs.Stats) => {\n stat;\n debugLog(chalk.cyan(`unlink in folder ${folder}`), filename);\n const h = this._filenameToHash[filename];\n if (h && index[h]) {\n delete index[h];\n }\n });\n w.on(\"add\", (filename: string, stat?: fs.Stats) => {\n stat;\n debugLog(chalk.cyan(`add in folder ${folder}`), filename); // stat);\n try {\n const certificate = readCertificate(filename);\n const info = exploreCertificate(certificate);\n const fingerprint = makeFingerprint(certificate);\n\n index[fingerprint] = {\n certificate,\n filename\n };\n this._filenameToHash[filename] = fingerprint;\n\n debugLog(\n chalk.magenta(\"CERT\"),\n info.tbsCertificate.subjectFingerPrint,\n info.tbsCertificate.serialNumber,\n info.tbsCertificate.extensions?.authorityKeyIdentifier?.authorityCertIssuerFingerPrint\n );\n } catch (err) {\n debugLog(`Walk files in folder ${folder} with file ${filename}`);\n debugLog(err);\n }\n });\n w.on(\"change\", (path: string, stat?: fs.Stats) => {\n stat;\n debugLog(\"change in folder \", folder, path);\n });\n this._watchers.push(w as unknown as fs.FSWatcher);\n await new Promise<void>((resolve, _reject) => {\n w.on(\"ready\", () => {\n debugLog(\"ready\");\n debugLog(Object.entries(index).map((kv) => (kv[0] as string).substring(0, 10)));\n resolve();\n });\n });\n }\n\n const promises: Promise<void>[] = [\n _walkAllFiles.bind(this, this.trustedFolder, this._thumbs.trusted)(),\n _walkAllFiles.bind(this, this.issuersCertFolder, this._thumbs.issuers.certs)(),\n _walkAllFiles.bind(this, this.rejectedFolder, this._thumbs.rejected)(),\n _walkCRLFiles.bind(this, this.crlFolder, this._thumbs.crl)(),\n _walkCRLFiles.bind(this, this.issuersCrlFolder, this._thumbs.issuersCrl)()\n ];\n await Promise.all(promises);\n await this.waitAndCheckCRLProcessingStatus();\n }\n\n // make sure that all crls have been processed.\n private async waitAndCheckCRLProcessingStatus(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this._pending_crl_to_process === 0) {\n setImmediate(resolve);\n return;\n }\n // istanbul ignore next\n if (this._on_crl_process) {\n return reject(new Error(\"Internal Error\"));\n }\n this._on_crl_process = resolve;\n });\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2022-2026 Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport { createCertificateSigningRequest, pemToPrivateKey, Subject } from \"node-opcua-crypto\";\nimport type { CreateCertificateSigningRequestWithConfigOptions } from \"../common\";\nimport { display, displaySubtitle } from \"../display\";\n\n/**\n * create a certificate signing request\n */\nexport async function createCertificateSigningRequestAsync(\n certificateSigningRequestFilename: string,\n params: CreateCertificateSigningRequestWithConfigOptions\n): Promise<void> {\n assert(params);\n assert(params.rootDir);\n assert(params.configFile);\n assert(params.privateKey);\n assert(typeof params.privateKey === \"string\");\n assert(fs.existsSync(params.privateKey), `Private key must exist${params.privateKey}`);\n\n // assert(fs.existsSync(params.configFile), \"config file must exist \" + params.configFile);\n assert(fs.existsSync(params.rootDir), \"RootDir key must exist\");\n assert(typeof certificateSigningRequestFilename === \"string\");\n\n const subject = params.subject ? new Subject(params.subject).toString() : undefined;\n displaySubtitle(\"- Creating a Certificate Signing Request with subtile\");\n\n const privateKeyPem = await fs.promises.readFile(params.privateKey, \"utf-8\");\n const privateKey = await pemToPrivateKey(privateKeyPem);\n\n const { csr } = await createCertificateSigningRequest({\n privateKey,\n dns: params.dns,\n ip: params.ip,\n subject,\n applicationUri: params.applicationUri,\n purpose: params.purpose\n });\n await fs.promises.writeFile(certificateSigningRequestFilename, csr, \"utf-8\");\n\n display(`- privateKey ${params.privateKey}`);\n display(`- certificateSigningRequestFilename ${certificateSigningRequestFilename}`);\n\n // to verify that the CSR is correct:\n // openssl req -in ./tmp/without_openssl.csr -noout -verify\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2022-2026 Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\n\nimport {\n CertificatePurpose,\n createSelfSignedCertificate as createSelfSignedCertificate1,\n pemToPrivateKey,\n Subject\n} from \"node-opcua-crypto\";\nimport { adjustDate, type CreateSelfSignCertificateWithConfigParam } from \"../common\";\nimport { displayTitle } from \"../display\";\n\nexport async function createSelfSignedCertificateAsync(\n certificate: string,\n params: CreateSelfSignCertificateWithConfigParam\n): Promise<void> {\n params.purpose = params.purpose || CertificatePurpose.ForApplication;\n assert(params.purpose, \"Please provide a Certificate Purpose\");\n /**\n * note: due to a limitation of openssl ,\n * it is not possible to control the startDate of the certificate validity\n * to achieve this the certificateAuthority tool shall be used.\n */\n assert(fs.existsSync(params.configFile));\n assert(fs.existsSync(params.rootDir));\n assert(fs.existsSync(params.privateKey));\n if (!params.subject) {\n throw Error(\"Missing subject\");\n }\n\n assert(typeof params.applicationUri === \"string\");\n assert(Array.isArray(params.dns));\n\n // xx no key size in self-signed assert(params.keySize == 2048 || params.keySize == 4096);\n\n // processAltNames(params);\n adjustDate(params);\n assert(Object.prototype.hasOwnProperty.call(params, \"validity\"));\n\n let subject: Subject | string = new Subject(params.subject);\n subject = subject.toString();\n\n // xx const certificateRequestFilename = certificate + \".csr\";\n const purpose = params.purpose;\n\n displayTitle(\"Generate a certificate request\");\n\n const privateKeyPem = await fs.promises.readFile(params.privateKey, \"utf-8\");\n const privateKey = await pemToPrivateKey(privateKeyPem);\n\n const { cert } = await createSelfSignedCertificate1({\n privateKey,\n notBefore: params.startDate,\n notAfter: params.endDate,\n validity: params.validity,\n dns: params.dns,\n ip: params.ip,\n subject,\n applicationUri: params.applicationUri,\n purpose\n });\n await fs.promises.writeFile(certificate, cert, \"utf-8\");\n}\n\nexport async function createSelfSignedCertificate(\n certificate: string,\n params: CreateSelfSignCertificateWithConfigParam\n): Promise<void> {\n await createSelfSignedCertificateAsync(certificate, params);\n}\n","const config =\n \"##################################################################################################\\n\" +\n \"## SIMPLE OPENSSL CONFIG FILE FOR SELF-SIGNED CERTIFICATE GENERATION\\n\" +\n \"################################################################################################################\\n\" +\n \"\\n\" +\n \"distinguished_name = req_distinguished_name\\n\" +\n \"default_md = sha1\\n\" +\n \"\\n\" +\n \"default_md = sha256 # The default digest algorithm\\n\" +\n \"\\n\" +\n \"[ v3_ca ]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid:always,issuer:always\\n\" +\n \"\\n\" +\n \"# authorityKeyIdentifier = keyid\\n\" +\n \"basicConstraints = CA:TRUE\\n\" +\n \"keyUsage = critical, cRLSign, keyCertSign\\n\" +\n 'nsComment = \"Self-signed Certificate for CA generated by Node-OPCUA Certificate utility\"\\n' +\n \"#nsCertType = sslCA, emailCA\\n\" +\n \"#subjectAltName = email:copy\\n\" +\n \"#issuerAltName = issuer:copy\\n\" +\n \"#obj = DER:02:03\\n\" +\n \"# crlDistributionPoints = @crl_info\\n\" +\n \"# [ crl_info ]\\n\" +\n \"# URI.0 = http://localhost:8900/crl.pem\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"\\n\" +\n \"[ req ]\\n\" +\n \"days = 390\\n\" +\n \"req_extensions = v3_req\\n\" +\n \"x509_extensions = v3_ca\\n\" +\n \"\\n\" +\n \"[v3_req]\\n\" +\n \"basicConstraints = CA:false\\n\" +\n \"keyUsage = critical, cRLSign, keyCertSign\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"\\n\" +\n \"[ v3_ca_signed]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid,issuer\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign\\n\" +\n \"extendedKeyUsage = clientAuth,serverAuth \\n\" +\n 'nsComment = \"certificate generated by Node-OPCUA Certificate utility and signed by a CA\"\\n' +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"[ v3_selfsigned]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid,issuer\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign\\n\" +\n \"extendedKeyUsage = clientAuth,serverAuth \\n\" +\n 'nsComment = \"Self-signed certificate generated by Node-OPCUA Certificate utility\"\\n' +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"[ req_distinguished_name ]\\n\" +\n \"countryName = Country Name (2 letter code)\\n\" +\n \"countryName_default = FR\\n\" +\n \"countryName_min = 2\\n\" +\n \"countryName_max = 2\\n\" +\n \"# stateOrProvinceName = State or Province Name (full name)\\n\" +\n \"# stateOrProvinceName_default = Ile de France\\n\" +\n \"# localityName = Locality Name (city, district)\\n\" +\n \"# localityName_default = Paris\\n\" +\n \"organizationName = Organization Name (company)\\n\" +\n \"organizationName_default = NodeOPCUA\\n\" +\n \"# organizationalUnitName = Organizational Unit Name (department, division)\\n\" +\n \"# organizationalUnitName_default = R&D\\n\" +\n \"commonName = Common Name (hostname, FQDN, IP, or your name)\\n\" +\n \"commonName_max = 256\\n\" +\n \"commonName_default = NodeOPCUA\\n\" +\n \"# emailAddress = Email Address\\n\" +\n \"# emailAddress_max = 40\\n\" +\n \"# emailAddress_default = node-opcua (at) node-opcua (dot) com\\n\" +\n \"subjectAltName = $ENV::ALTNAME\";\n\nexport default config;\n"],"mappings":"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","names":["import_node_assert","import_node_fs","import_node_path","import_chalk","import_node_opcua_crypto","assert","import_node_assert","fs","chalk","path","assert","import_chalk","chalk","import_node_assert","import_node_fs","import_node_path","import_node_assert","import_node_child_process","import_node_fs","import_node_os","import_byline","import_chalk","import_node_fs","import_node_path","import_chalk","doDebug","url","chalk","child_process","byline","quote","path","os","fs","opensslFolder","opensslExecPath","ProgressBar","wget","yauzl","execute","chalk","child_process","byline","os","fs","assert","chalk","execute","import_node_assert","import_node_fs","import_node_path","path","fs","n","assert","s","assert","fs","n","q","n","assert","fs","path","config","n","q","assert","path","fs","chalk","dns","import_node_assert","import_node_fs","import_node_os","import_node_path","import_chalk","import_node_opcua_crypto","import_node_assert","assert","import_node_os","os","dns","import_node_assert","import_node_fs","import_node_path","import_chalk","import_node_opcua_crypto","import_node_assert","import_node_fs","import_node_opcua_crypto","assert","fs","import_node_assert","import_node_fs","import_node_opcua_crypto","assert","fs","createSelfSignedCertificate1","config","fs","VerificationStatus","fingerprint","CertificateManagerState","assert","path","chalk","today","chokidar","construct_CertificateAuthority","assert","fs","path","default_config_template","assert","fqdn","os","chalk","dns","applicationUri","ip","createSelfSignedCertificate","construct_CertificateAuthority","commandLineUsage","commandLineArgs","local_argv"]}
1
+ {"version":3,"sources":["../lib/index.ts","../lib/ca/certificate_authority.ts","../lib/toolbox/common.ts","../lib/toolbox/common2.ts","../lib/toolbox/config.ts","../lib/toolbox/debug.ts","../lib/toolbox/display.ts","../lib/toolbox/with_openssl/index.ts","../lib/toolbox/with_openssl/_env.ts","../lib/toolbox/with_openssl/create_certificate_signing_request.ts","../lib/misc/subject.ts","../lib/toolbox/with_openssl/execute_openssl.ts","../lib/toolbox/with_openssl/install_prerequisite.ts","../lib/toolbox/with_openssl/toolbox.ts","../lib/ca/templates/ca_config_template.cnf.ts","../lib/ca/crypto_create_CA.ts","../lib/misc/applicationurn.ts","../lib/misc/hostname.ts","../lib/pki/certificate_manager.ts","../lib/toolbox/without_openssl/create_certificate_signing_request.ts","../lib/toolbox/without_openssl/create_self_signed_certificate.ts","../lib/pki/templates/simple_config_template.cnf.ts"],"sourcesContent":["// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport { CertificateAuthority, type CertificateAuthorityOptions } from \"./ca/certificate_authority\";\nexport { main as pki_main } from \"./ca/crypto_create_CA\";\nexport * from \"./misc/subject\";\nexport * from \"./pki/certificate_manager\";\nexport * from \"./toolbox/index\";\nexport { install_prerequisite } from \"./toolbox/with_openssl/install_prerequisite\";\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-shadowed-variable\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n exploreCertificateSigningRequest,\n generatePrivateKeyFile,\n readCertificateSigningRequest,\n Subject,\n type SubjectOptions\n} from \"node-opcua-crypto\";\n\nimport {\n adjustApplicationUri,\n adjustDate,\n certificateFileExist,\n debugLog,\n displaySubtitle,\n displayTitle,\n type Filename,\n type KeySize,\n makePath,\n mkdirRecursiveSync,\n type Params,\n type ProcessAltNamesParam,\n quote\n} from \"../toolbox\";\n\nimport {\n type ExecuteOpenSSLOptions,\n type ExecuteOptions,\n ensure_openssl_installed,\n execute_openssl,\n execute_openssl_no_failure,\n generateStaticConfig,\n processAltNames,\n setEnv,\n x509Date\n} from \"../toolbox/with_openssl\";\n\nexport const defaultSubject = \"/C=FR/ST=IDF/L=Paris/O=Local NODE-OPCUA Certificate Authority/CN=NodeOPCUA-CA\";\n\nimport _ca_config_template from \"./templates/ca_config_template.cnf\";\n\n// tslint:disable-next-line:variable-name\nexport const configurationFileTemplate: string = _ca_config_template;\n\nconst config = {\n certificateDir: \"INVALID\",\n forceCA: false,\n pkiDir: \"INVALID\"\n};\n\nconst n = makePath;\nconst q = quote;\n\n// convert 'c07b9179' to \"192.123.145.121\"\nfunction octetStringToIpAddress(a: string) {\n return (\n parseInt(a.substring(0, 2), 16).toString() +\n \".\" +\n parseInt(a.substring(2, 4), 16).toString() +\n \".\" +\n parseInt(a.substring(4, 6), 16).toString() +\n \".\" +\n parseInt(a.substring(6, 8), 16).toString()\n );\n}\nassert(octetStringToIpAddress(\"c07b9179\") === \"192.123.145.121\");\nasync function construct_CertificateAuthority(certificateAuthority: CertificateAuthority): Promise<void> {\n // create the CA directory store\n // create the CA directory store\n //\n // PKI/CA\n // |\n // +-+> private\n // |\n // +-+> public\n // |\n // +-+> certs\n // |\n // +-+> crl\n // |\n // +-+> conf\n // |\n // +-f: serial\n // +-f: crlNumber\n // +-f: index.txt\n //\n\n const subject = certificateAuthority.subject;\n\n const caRootDir = path.resolve(certificateAuthority.rootDir);\n\n async function make_folders() {\n mkdirRecursiveSync(caRootDir);\n mkdirRecursiveSync(path.join(caRootDir, \"private\"));\n mkdirRecursiveSync(path.join(caRootDir, \"public\"));\n // xx execute(\"chmod 700 private\");\n mkdirRecursiveSync(path.join(caRootDir, \"certs\"));\n mkdirRecursiveSync(path.join(caRootDir, \"crl\"));\n mkdirRecursiveSync(path.join(caRootDir, \"conf\"));\n }\n await make_folders();\n\n async function construct_default_files() {\n const serial = path.join(caRootDir, \"serial\");\n if (!fs.existsSync(serial)) {\n await fs.promises.writeFile(serial, \"1000\");\n }\n\n const crlNumber = path.join(caRootDir, \"crlnumber\");\n if (!fs.existsSync(crlNumber)) {\n await fs.promises.writeFile(crlNumber, \"1000\");\n }\n\n const indexFile = path.join(caRootDir, \"index.txt\");\n if (!fs.existsSync(indexFile)) {\n await fs.promises.writeFile(indexFile, \"\");\n }\n }\n\n await construct_default_files();\n\n if (fs.existsSync(path.join(caRootDir, \"private/cakey.pem\")) && !config.forceCA) {\n // certificate already exists => do not overwrite\n debugLog(\"CA private key already exists ... skipping\");\n return;\n }\n\n // tslint:disable:no-empty\n displayTitle(\"Create Certificate Authority (CA)\");\n\n const indexFileAttr = path.join(caRootDir, \"index.txt.attr\");\n if (!fs.existsSync(indexFileAttr)) {\n await fs.promises.writeFile(indexFileAttr, \"unique_subject = no\");\n }\n\n const caConfigFile = certificateAuthority.configFile;\n if (1 || !fs.existsSync(caConfigFile)) {\n let data = configurationFileTemplate; // inlineText(configurationFile);\n data = makePath(data.replace(/%%ROOT_FOLDER%%/, caRootDir));\n\n await fs.promises.writeFile(caConfigFile, data);\n }\n\n // http://www.akadia.com/services/ssh_test_certificate.html\n const subjectOpt = ` -subj \"${subject.toString()}\" `;\n processAltNames({} as Params);\n\n const options = { cwd: caRootDir };\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", options);\n const configOption = ` -config ${q(n(configFile))}`;\n\n const keySize = certificateAuthority.keySize;\n\n const privateKeyFilename = path.join(caRootDir, \"private/cakey.pem\");\n const csrFilename = path.join(caRootDir, \"private/cakey.csr\");\n\n displayTitle(`Generate the CA private Key - ${keySize}`);\n // The first step is to create your RSA Private Key.\n // This key is a 1025,2048,3072 or 2038 bit RSA key which is encrypted using\n // Triple-DES and stored in a PEM format so that it is readable as ASCII text.\n await generatePrivateKeyFile(privateKeyFilename, keySize);\n displayTitle(\"Generate a certificate request for the CA key\");\n // Once the private key is generated a Certificate Signing Request can be generated.\n // The CSR is then used in one of two ways. Ideally, the CSR will be sent to a Certificate Authority, such as\n // Thawte or Verisign who will verify the identity of the requestor and issue a signed certificate.\n // The second option is to self-sign the CSR, which will be demonstrated in the next section\n await execute_openssl(\n \"req -new\" +\n \" -sha256 \" +\n \" -text \" +\n \" -extensions v3_ca\" +\n configOption +\n \" -key \" +\n q(n(privateKeyFilename)) +\n \" -out \" +\n q(n(csrFilename)) +\n \" \" +\n subjectOpt,\n options\n );\n\n // xx // Step 3: Remove Passphrase from Key\n // xx execute(\"cp private/cakey.pem private/cakey.pem.org\");\n // xx execute(openssl_path + \" rsa -in private/cakey.pem.org -out private/cakey.pem -passin pass:\"+paraphrase);\n\n displayTitle(\"Generate CA Certificate (self-signed)\");\n await execute_openssl(\n \" x509 -sha256 -req -days 3650 \" +\n \" -text \" +\n \" -extensions v3_ca\" +\n \" -extfile \" +\n q(n(configFile)) +\n \" -in private/cakey.csr \" +\n \" -signkey \" +\n q(n(privateKeyFilename)) +\n \" -out public/cacert.pem\",\n options\n );\n displaySubtitle(\"generate initial CRL (Certificate Revocation List)\");\n await regenerateCrl(certificateAuthority.revocationList, configOption, options);\n displayTitle(\"Create Certificate Authority (CA) ---> DONE\");\n}\n\nasync function regenerateCrl(revocationList: string, configOption: string, options: ExecuteOpenSSLOptions) {\n // produce a CRL in PEM format\n displaySubtitle(\"regenerate CRL (Certificate Revocation List)\");\n await execute_openssl(`ca -gencrl ${configOption} -out crl/revocation_list.crl`, options);\n await execute_openssl(\"crl \" + \" -in crl/revocation_list.crl -out crl/revocation_list.der \" + \" -outform der\", options);\n\n displaySubtitle(\"Display (Certificate Revocation List)\");\n await execute_openssl(`crl -in ${q(n(revocationList))} -text -noout`, options);\n}\n\nexport interface CertificateAuthorityOptions {\n keySize: KeySize;\n location: string;\n subject?: string | SubjectOptions;\n}\n\nexport class CertificateAuthority {\n public readonly keySize: KeySize;\n public readonly location: string;\n public readonly subject: Subject;\n\n constructor(options: CertificateAuthorityOptions) {\n assert(Object.prototype.hasOwnProperty.call(options, \"location\"));\n assert(Object.prototype.hasOwnProperty.call(options, \"keySize\"));\n this.location = options.location;\n this.keySize = options.keySize || 2048;\n this.subject = new Subject(options.subject || defaultSubject);\n }\n\n public get rootDir() {\n return this.location;\n }\n\n public get configFile() {\n return path.normalize(path.join(this.rootDir, \"./conf/caconfig.cnf\"));\n }\n\n public get caCertificate() {\n // the Certificate Authority Certificate\n return makePath(this.rootDir, \"./public/cacert.pem\");\n }\n\n /**\n * the file name where the current Certificate Revocation List is stored (in DER format)\n */\n public get revocationListDER() {\n return makePath(this.rootDir, \"./crl/revocation_list.der\");\n }\n\n /**\n * the file name where the current Certificate Revocation List is stored (in PEM format)\n */\n public get revocationList() {\n return makePath(this.rootDir, \"./crl/revocation_list.crl\");\n }\n\n public get caCertificateWithCrl() {\n return makePath(this.rootDir, \"./public/cacertificate_with_crl.pem\");\n }\n\n public async initialize(): Promise<void> {\n await construct_CertificateAuthority(this);\n }\n\n public async constructCACertificateWithCRL(): Promise<void> {\n const cacertWithCRL = this.caCertificateWithCrl;\n\n // note : in order to check if the certificate is revoked,\n // you need to specify -crl_check and have both the CA cert and the (applicable) CRL in your trust store.\n // There are two ways to do that:\n // 1. concatenate cacert.pem and crl.pem into one file and use that for -CAfile.\n // 2. use some linked\n // ( from http://security.stackexchange.com/a/58305/59982)\n\n if (fs.existsSync(this.revocationList)) {\n await fs.promises.writeFile(\n cacertWithCRL,\n fs.readFileSync(this.caCertificate, \"utf8\") + fs.readFileSync(this.revocationList, \"utf8\")\n );\n } else {\n // there is no revocation list yet\n await fs.promises.writeFile(cacertWithCRL, fs.readFileSync(this.caCertificate));\n }\n }\n\n public async constructCertificateChain(certificate: Filename): Promise<void> {\n assert(fs.existsSync(certificate));\n assert(fs.existsSync(this.caCertificate));\n\n debugLog(chalk.yellow(\" certificate file :\"), chalk.cyan(certificate));\n // append\n await fs.promises.writeFile(\n certificate,\n (await fs.promises.readFile(certificate, \"utf8\")) + (await fs.promises.readFile(this.caCertificate, \"utf8\"))\n // + fs.readFileSync(this.revocationList)\n );\n }\n\n public async createSelfSignedCertificate(certificateFile: Filename, privateKey: Filename, params: Params): Promise<void> {\n assert(typeof privateKey === \"string\");\n assert(fs.existsSync(privateKey));\n\n if (!certificateFileExist(certificateFile)) {\n return;\n }\n\n adjustDate(params);\n adjustApplicationUri(params);\n processAltNames(params);\n\n const csrFile = `${certificateFile}_csr`;\n assert(csrFile);\n const configFile = generateStaticConfig(this.configFile, { cwd: this.rootDir });\n\n const options = {\n cwd: this.rootDir,\n openssl_conf: makePath(configFile)\n };\n\n const configOption = \"\";\n\n const subject = params.subject ? new Subject(params.subject).toString() : \"\";\n const subjectOptions = subject && subject.length > 1 ? ` -subj ${subject} ` : \"\";\n\n displaySubtitle(\"- the certificate signing request\");\n await execute_openssl(\n \"req \" +\n \" -new -sha256 -text \" +\n configOption +\n subjectOptions +\n \" -batch -key \" +\n q(n(privateKey)) +\n \" -out \" +\n q(n(csrFile)),\n options\n );\n\n displaySubtitle(\"- creating the self-signed certificate\");\n await execute_openssl(\n \"ca \" +\n \" -selfsign \" +\n \" -keyfile \" +\n q(n(privateKey)) +\n \" -startdate \" +\n x509Date(params.startDate) +\n \" -enddate \" +\n x509Date(params.endDate) +\n \" -batch -out \" +\n q(n(certificateFile)) +\n \" -in \" +\n q(n(csrFile)),\n options\n );\n\n displaySubtitle(\"- dump the certificate for a check\");\n\n await execute_openssl(`x509 -in ${q(n(certificateFile))} -dates -fingerprint -purpose -noout`, {});\n\n displaySubtitle(\"- verify self-signed certificate\");\n await execute_openssl_no_failure(`verify -verbose -CAfile ${q(n(certificateFile))} ${q(n(certificateFile))}`, options);\n\n await fs.promises.unlink(csrFile);\n }\n\n /**\n * revoke a certificate and update the CRL\n *\n * @method revokeCertificate\n * @param certificate - the certificate to revoke\n * @param params\n * @param [params.reason = \"keyCompromise\" {String}]\n * @async\n */\n public async revokeCertificate(certificate: Filename, params: Params): Promise<void> {\n const crlReasons = [\n \"unspecified\",\n \"keyCompromise\",\n \"CACompromise\",\n \"affiliationChanged\",\n \"superseded\",\n \"cessationOfOperation\",\n \"certificateHold\",\n \"removeFromCRL\"\n ];\n\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", { cwd: this.rootDir });\n\n const options = {\n cwd: this.rootDir,\n openssl_conf: makePath(configFile)\n };\n\n setEnv(\"ALTNAME\", \"\");\n const randomFile = path.join(this.rootDir, \"random.rnd\");\n setEnv(\"RANDFILE\", randomFile);\n\n // // tslint:disable-next-line:no-string-literal\n // if (!fs.existsSync((process.env as any)[\"OPENSSL_CONF\"])) {\n // throw new Error(\"Cannot find OPENSSL_CONF\");\n // }\n\n const configOption = ` -config ${q(n(configFile))}`;\n\n const reason = params.reason || \"keyCompromise\";\n assert(crlReasons.indexOf(reason) >= 0);\n\n displayTitle(`Revoking certificate ${certificate}`);\n\n displaySubtitle(\"Revoke certificate\");\n\n await execute_openssl_no_failure(`ca -verbose ${configOption} -revoke ${q(certificate)} -crl_reason ${reason}`, options);\n // regenerate CRL (Certificate Revocation List)\n await regenerateCrl(this.revocationList, configOption, options);\n\n displaySubtitle(\"Verify that certificate is revoked\");\n\n await execute_openssl_no_failure(\n \"verify -verbose\" +\n // configOption +\n \" -CRLfile \" +\n q(n(this.revocationList)) +\n \" -CAfile \" +\n q(n(this.caCertificate)) +\n \" -crl_check \" +\n q(n(certificate)),\n options\n );\n\n // produce CRL in DER format\n displaySubtitle(\"Produce CRL in DER form \");\n await execute_openssl(`crl -in ${q(n(this.revocationList))} -out crl/revocation_list.der -outform der`, options);\n // produce CRL in PEM format with text\n displaySubtitle(\"Produce CRL in PEM form \");\n\n await execute_openssl(`crl -in ${q(n(this.revocationList))} -out crl/revocation_list.pem -outform pem -text `, options);\n }\n\n /**\n *\n * @param certificate - the certificate filename to generate\n * @param certificateSigningRequestFilename - the certificate signing request\n * @param params - parameters\n * @param params.applicationUri - the applicationUri\n * @param params.startDate - startDate of the certificate\n * @param params.validity - number of day of validity of the certificate\n */\n public async signCertificateRequest(\n certificate: Filename,\n certificateSigningRequestFilename: Filename,\n params1: Params\n ): Promise<Filename> {\n await ensure_openssl_installed();\n assert(fs.existsSync(certificateSigningRequestFilename));\n if (!certificateFileExist(certificate)) {\n return \"\";\n }\n adjustDate(params1);\n adjustApplicationUri(params1);\n processAltNames(params1);\n\n const options: ExecuteOptions = { cwd: this.rootDir };\n\n // note :\n // subjectAltName is not copied across\n // see https://github.com/openssl/openssl/issues/10458\n const csr = await readCertificateSigningRequest(certificateSigningRequestFilename);\n const csrInfo = exploreCertificateSigningRequest(csr);\n\n const applicationUri = csrInfo.extensionRequest.subjectAltName.uniformResourceIdentifier\n ? csrInfo.extensionRequest.subjectAltName.uniformResourceIdentifier[0]\n : undefined;\n if (typeof applicationUri !== \"string\") {\n throw new Error(\"Cannot find applicationUri in CSR\");\n }\n\n const dns = csrInfo.extensionRequest.subjectAltName.dNSName || [];\n let ip = csrInfo.extensionRequest.subjectAltName.iPAddress || [];\n ip = ip.map(octetStringToIpAddress);\n\n const params: ProcessAltNamesParam = {\n applicationUri,\n dns,\n ip\n };\n\n processAltNames(params);\n\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", options);\n\n displaySubtitle(\"- then we ask the authority to sign the certificate signing request\");\n\n const configOption = ` -config ${configFile}`;\n await execute_openssl(\n \"ca \" +\n configOption +\n \" -startdate \" +\n x509Date(params1.startDate) +\n \" -enddate \" +\n x509Date(params1.endDate) +\n \" -batch -out \" +\n q(n(certificate)) +\n \" -in \" +\n q(n(certificateSigningRequestFilename)),\n options\n );\n\n displaySubtitle(\"- dump the certificate for a check\");\n await execute_openssl(`x509 -in ${q(n(certificate))} -dates -fingerprint -purpose -noout`, options);\n\n displaySubtitle(\"- construct CA certificate with CRL\");\n await this.constructCACertificateWithCRL();\n\n // construct certificate chain\n // concatenate certificate with CA Certificate and revocation list\n displaySubtitle(\"- construct certificate chain\");\n await this.constructCertificateChain(certificate);\n // todo\n displaySubtitle(\"- verify certificate against the root CA\");\n await this.verifyCertificate(certificate);\n\n return certificate;\n }\n\n public async verifyCertificate(certificate: Filename): Promise<void> {\n // openssl verify crashes on windows! we cannot use it reliably\n // istanbul ignore next\n const isImplemented = false;\n\n // istanbul ignore next\n if (isImplemented) {\n const options = { cwd: this.rootDir };\n const configFile = generateStaticConfig(\"conf/caconfig.cnf\", options);\n\n setEnv(\"OPENSSL_CONF\", makePath(configFile));\n const _configOption = ` -config ${configFile}`;\n _configOption;\n await execute_openssl_no_failure(\n `verify -verbose -CAfile ${q(n(this.caCertificateWithCrl))} ${q(n(certificate))}`,\n options\n );\n }\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\n\nexport type KeySize = 1024 | 2048 | 3072 | 4096;\nexport type Thumbprint = string;\nexport type Filename = string;\nexport type CertificateStatus = \"unknown\" | \"trusted\" | \"rejected\";\n\nimport type { CertificatePurpose } from \"node-opcua-crypto\";\nimport type { SubjectOptions } from \"../misc/subject\";\n\nexport type KeyLength = 1024 | 2048 | 3072 | 4096;\n\nexport function quote(str?: string): string {\n return `\"${str || \"\"}\"`;\n}\n\nexport interface ProcessAltNamesParam {\n dns?: string[];\n ip?: string[];\n applicationUri?: string;\n}\n\n// tslint:disable-next:no-empty-interface\nexport interface CreateCertificateSigningRequestOptions extends ProcessAltNamesParam {\n subject?: SubjectOptions | string;\n}\n\nexport interface CreateCertificateSigningRequestWithConfigOptions extends CreateCertificateSigningRequestOptions {\n rootDir: Filename;\n configFile: Filename;\n privateKey: Filename;\n purpose: CertificatePurpose;\n}\n\nexport interface StartDateEndDateParam {\n startDate?: Date;\n endDate?: Date;\n validity?: number;\n}\n\nexport interface CreateSelfSignCertificateParam extends ProcessAltNamesParam, StartDateEndDateParam {\n subject?: SubjectOptions | string;\n}\n\n// purpose of self-signed certificate\n\nexport interface CreateSelfSignCertificateWithConfigParam extends CreateSelfSignCertificateParam {\n rootDir: Filename;\n configFile: Filename;\n privateKey: Filename;\n purpose: CertificatePurpose;\n}\n\nexport interface Params extends ProcessAltNamesParam, StartDateEndDateParam {\n subject?: SubjectOptions | string;\n\n privateKey?: string;\n configFile?: string;\n rootDir?: string;\n\n outputFile?: string;\n reason?: string;\n}\n\nexport function adjustDate(params: StartDateEndDateParam) {\n assert(params instanceof Object);\n params.startDate = params.startDate || new Date();\n assert(params.startDate instanceof Date);\n\n params.validity = params.validity || 365; // one year\n\n params.endDate = new Date(params.startDate.getTime());\n params.endDate.setDate(params.startDate.getDate() + params.validity);\n\n // params.endDate = x509Date(endDate);\n // params.startDate = x509Date(startDate);\n\n assert(params.endDate instanceof Date);\n assert(params.startDate instanceof Date);\n\n // // istanbul ignore next\n // if (!g_config.silent) {\n // warningLog(\" start Date \", params.startDate.toUTCString(), x509Date(params.startDate));\n // warningLog(\" end Date \", params.endDate.toUTCString(), x509Date(params.endDate));\n // }\n}\n\nexport function adjustApplicationUri(params: Params) {\n const applicationUri = params.applicationUri || \"\";\n if (applicationUri.length > 200) {\n throw new Error(`Openssl doesn't support urn with length greater than 200${applicationUri}`);\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport chalk from \"chalk\";\n\nimport { g_config } from \"./config\";\n\nimport { debugLog, warningLog } from \"./debug\";\n\nexport function certificateFileExist(certificateFile: string): boolean {\n // istanbul ignore next\n if (fs.existsSync(certificateFile) && !g_config.force) {\n warningLog(\n chalk.yellow(\" certificate \") + chalk.cyan(certificateFile) + chalk.yellow(\" already exists => do not overwrite\")\n );\n return false;\n }\n return true;\n}\n\nexport function mkdirRecursiveSync(folder: string): void {\n if (!fs.existsSync(folder)) {\n // istanbul ignore next\n debugLog(chalk.white(\" .. constructing \"), folder);\n fs.mkdirSync(folder, { recursive: true });\n }\n}\n\nexport function makePath(folderName: string, filename?: string): string {\n let s: string;\n if (filename) {\n s = path.join(path.normalize(folderName), filename);\n } else {\n assert(folderName);\n s = folderName;\n }\n s = s.replace(/\\\\/g, \"/\");\n return s;\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nexport const g_config = {\n opensslVersion: \"unset\",\n silent: process.env.VERBOSE ? !process.env.VERBOSE : true,\n force: false\n};\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nexport const doDebug = process.env.NODEOPCUAPKIDEBUG || false;\nexport const displayError = true;\nexport const displayDebug = !!process.env.NODEOPCUAPKIDEBUG || false;\n// tslint:disable-next-line:no-empty\nexport function debugLog(...args: unknown[]) {\n // istanbul ignore next\n if (displayDebug) {\n console.log.apply(null, args);\n }\n}\nexport function warningLog(...args: unknown[]) {\n console.log.apply(null, args);\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport chalk from \"chalk\";\nimport { g_config } from \"./config\";\nimport { warningLog } from \"./debug\";\n\n// istanbul ignore next\nexport function displayChapter(str: string) {\n const l = \" \";\n warningLog(`${chalk.bgWhite(l)} `);\n str = ` ${str}${l}`.substring(0, l.length);\n warningLog(chalk.bgWhite.cyan(str));\n warningLog(`${chalk.bgWhite(l)} `);\n}\n\nexport function displayTitle(str: string) {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(\"\");\n warningLog(chalk.yellowBright(str));\n warningLog(chalk.yellow(new Array(str.length + 1).join(\"=\")), \"\\n\");\n }\n}\n\nexport function displaySubtitle(str: string) {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(\"\");\n warningLog(` ${chalk.yellowBright(str)}`);\n warningLog(` ${chalk.white(new Array(str.length + 1).join(\"-\"))}`, \"\\n\");\n }\n}\nexport function display(str: string) {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(` ${str}`);\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport exp from \"node:constants\";\n\nconst _exp = exp;\n\nexport * from \"./_env\";\nexport * from \"./create_certificate_signing_request\";\nexport * from \"./execute_openssl\";\nexport * from \"./install_prerequisite\";\nexport * from \"./toolbox\";\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport type { ProcessAltNamesParam } from \"../common\";\nimport { g_config } from \"../config\";\nimport { warningLog } from \"../debug\";\n\nexport const exportedEnvVars: Record<string, string> = {};\n\nexport function setEnv(varName: string, value: string): void {\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(` set ${varName}=${value}`);\n }\n exportedEnvVars[varName] = value;\n\n if ([\"OPENSSL_CONF\"].indexOf(varName) >= 0) {\n process.env[varName] = value;\n }\n if ([\"RANDFILE\"].indexOf(varName) >= 0) {\n process.env[varName] = value;\n }\n}\n\nexport function hasEnv(varName: string): boolean {\n return Object.prototype.hasOwnProperty.call(exportedEnvVars, varName);\n}\nexport function getEnv(varName: string): string {\n return exportedEnvVars[varName];\n}\n\nexport function getEnvironmentVarNames(): { key: string; pattern: string }[] {\n return Object.keys(exportedEnvVars).map((varName: string) => {\n return { key: varName, pattern: `\\\\$ENV\\\\:\\\\:${varName}` };\n });\n}\n\nexport function processAltNames(params: ProcessAltNamesParam) {\n params.dns = params.dns || [];\n params.ip = params.ip || [];\n\n // construct subjectAtlName\n let subjectAltName: string[] = [];\n subjectAltName.push(`URI:${params.applicationUri}`);\n subjectAltName = ([] as string[]).concat(\n subjectAltName,\n params.dns.map((d: string) => `DNS:${d}`)\n );\n subjectAltName = ([] as string[]).concat(\n subjectAltName,\n params.ip.map((d: string) => `IP:${d}`)\n );\n const subjectAltNameString = subjectAltName.join(\", \");\n setEnv(\"ALTNAME\", subjectAltNameString);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { Subject } from \"../../misc/subject\";\nimport { type CreateCertificateSigningRequestWithConfigOptions, quote } from \"../common\";\nimport { makePath } from \"../common2\";\nimport { displaySubtitle } from \"../display\";\nimport { processAltNames } from \"./_env\";\nimport { execute_openssl } from \"./execute_openssl\";\nimport { generateStaticConfig } from \"./toolbox\";\n\nconst q = quote;\nconst n = makePath;\n\n/**\n * create a certificate signing request\n */\nexport async function createCertificateSigningRequestWithOpenSSL(\n certificateSigningRequestFilename: string,\n params: CreateCertificateSigningRequestWithConfigOptions\n): Promise<void> {\n assert(params);\n assert(params.rootDir);\n assert(params.configFile);\n assert(params.privateKey);\n assert(typeof params.privateKey === \"string\");\n assert(fs.existsSync(params.configFile), `config file must exist ${params.configFile}`);\n assert(fs.existsSync(params.privateKey), `Private key must exist${params.privateKey}`);\n assert(fs.existsSync(params.rootDir), \"RootDir key must exist\");\n assert(typeof certificateSigningRequestFilename === \"string\");\n\n // note : this openssl command requires a config file\n processAltNames(params);\n const configFile = generateStaticConfig(params.configFile, { cwd: params.rootDir });\n\n const options = { cwd: params.rootDir, openssl_conf: path.relative(params.rootDir, configFile) };\n\n const configOption = ` -config ${q(n(configFile))}`;\n\n const subject = params.subject ? new Subject(params.subject).toString() : undefined;\n // process.env.OPENSSL_CONF =\"\";\n const subjectOptions = subject ? ` -subj \"${subject}\"` : \"\";\n\n displaySubtitle(\"- Creating a Certificate Signing Request with openssl\");\n await execute_openssl(\n \"req -new\" +\n \" -sha256 \" +\n \" -batch \" +\n \" -text \" +\n configOption +\n \" -key \" +\n q(n(params.privateKey)) +\n subjectOptions +\n \" -out \" +\n q(n(certificateSigningRequestFilename)),\n options\n );\n}\n","export type { SubjectOptions } from \"node-opcua-crypto\";\nexport { Subject } from \"node-opcua-crypto\";\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\nimport child_process from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport byline from \"byline\";\nimport chalk from \"chalk\";\nimport { quote } from \"../common\";\nimport { makePath } from \"../common2\";\nimport { g_config } from \"../config\";\nimport { debugLog, displayError, doDebug, warningLog } from \"../debug\";\nimport { setEnv } from \"./_env\";\nimport { get_openssl_exec_path } from \"./install_prerequisite\";\n\n// tslint:disable-next-line:variable-name\n\nlet opensslPath: string | undefined; // not initialized\n\nconst n = makePath;\n\nexport interface ExecuteOptions {\n cwd?: string;\n hideErrorMessage?: boolean;\n}\n\nexport async function execute(cmd: string, options: ExecuteOptions): Promise<string> {\n const from = new Error();\n\n options.cwd = options.cwd || process.cwd();\n\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(chalk.cyan(\" CWD \"), options.cwd);\n }\n\n const outputs: string[] = [];\n\n return await new Promise((resolve, reject) => {\n const child = child_process.exec(\n cmd,\n {\n cwd: options.cwd,\n windowsHide: true\n },\n (err: child_process.ExecException | null) => {\n // istanbul ignore next\n if (err) {\n if (!options.hideErrorMessage) {\n const fence = \"###########################################\";\n console.error(chalk.bgWhiteBright.redBright(`${fence} OPENSSL ERROR ${fence}`));\n console.error(chalk.bgWhiteBright.redBright(`CWD = ${options.cwd}`));\n console.error(chalk.bgWhiteBright.redBright(err.message));\n console.error(chalk.bgWhiteBright.redBright(`${fence} OPENSSL ERROR ${fence}`));\n\n console.error(from.stack);\n }\n reject(new Error(err.message));\n return;\n }\n resolve(outputs.join(\"\"));\n }\n );\n\n if (child.stdout) {\n const stream2 = byline(child.stdout);\n stream2.on(\"data\", (line: string) => {\n outputs.push(`${line}\\n`);\n });\n if (!g_config.silent) {\n stream2.on(\"data\", (line: string) => {\n line = line.toString();\n if (doDebug) {\n process.stdout.write(`${chalk.white(\" stdout \") + chalk.whiteBright(line)}\\n`);\n }\n });\n }\n }\n\n // istanbul ignore next\n if (!g_config.silent) {\n if (child.stderr) {\n const stream1 = byline(child.stderr);\n stream1.on(\"data\", (line: string) => {\n line = line.toString();\n if (displayError) {\n process.stdout.write(`${chalk.white(\" stderr \") + chalk.red(line)}\\n`);\n }\n });\n }\n }\n });\n}\n\nexport async function find_openssl(): Promise<string> {\n return await get_openssl_exec_path();\n}\n\nexport async function ensure_openssl_installed(): Promise<void> {\n if (!opensslPath) {\n opensslPath = await find_openssl();\n const outputs = await execute_openssl(\"version\", { cwd: \".\" });\n g_config.opensslVersion = outputs.trim();\n if (doDebug) {\n warningLog(\"OpenSSL version : \", g_config.opensslVersion);\n }\n }\n}\n\nexport async function executeOpensslAsync(cmd: string, options: ExecuteOpenSSLOptions): Promise<string> {\n return await execute_openssl(cmd, options);\n}\n\nexport async function execute_openssl_no_failure(cmd: string, options: ExecuteOpenSSLOptions) {\n options = options || {};\n options.hideErrorMessage = true;\n try {\n return await execute_openssl(cmd, options);\n } catch (err) {\n debugLog(\" (ignored error = ERROR : )\", (err as Error).message);\n }\n}\n\nfunction getTempFolder(): string {\n return os.tmpdir();\n}\n\nexport interface ExecuteOpenSSLOptions extends ExecuteOptions {\n openssl_conf?: string;\n}\n\nexport async function execute_openssl(cmd: string, options: ExecuteOpenSSLOptions): Promise<string> {\n debugLog(\"execute_openssl\", cmd, options);\n const empty_config_file = n(getTempFolder(), \"empty_config.cnf\");\n if (!fs.existsSync(empty_config_file)) {\n await fs.promises.writeFile(empty_config_file, \"# empty config file\");\n }\n\n options = options || {};\n options.openssl_conf = options.openssl_conf || empty_config_file; // \"!! OPEN SLL CONF NOT DEFINED BAD FILE !!\";\n assert(options.openssl_conf);\n setEnv(\"OPENSSL_CONF\", options.openssl_conf);\n\n // istanbul ignore next\n if (!g_config.silent) {\n warningLog(chalk.cyan(\" OPENSSL_CONF\"), process.env.OPENSSL_CONF);\n warningLog(chalk.cyan(\" RANDFILE \"), process.env.RANDFILE);\n warningLog(chalk.cyan(\" CMD openssl \"), chalk.cyanBright(cmd));\n }\n await ensure_openssl_installed();\n return await execute(`${quote(opensslPath)} ${cmd}`, options);\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport child_process from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { Readable } from \"node:stream\";\nimport url from \"node:url\";\n\nimport byline from \"byline\";\nimport chalk from \"chalk\";\nimport ProgressBar from \"progress\";\nimport wget from \"wget-improved-2\";\nimport yauzl from \"yauzl\";\n\nimport { warningLog } from \"../debug\";\n\nconst doDebug = process.env.NODEOPCUAPKIDEBUG || false;\n\ndeclare interface ProxyOptions {\n host: string;\n port: number;\n localAddress?: string;\n proxyAuth?: string;\n headers?: Record<string, string>;\n protocol: string; // \"https\" | \"http\"\n}\ndeclare interface WgetOptions {\n gunzip?: boolean;\n proxy?: ProxyOptions;\n}\n\ndeclare interface WgetInterface {\n download(url: string, outputFilename: string, options: WgetOptions): NodeJS.EventEmitter;\n}\n\ninterface ExecuteResult {\n exitCode: number;\n output: string;\n}\n\nfunction makeOptions(): WgetOptions {\n const proxy =\n process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || undefined;\n if (proxy) {\n const a = new url.URL(proxy);\n const auth = a.username ? `${a.username}:${a.password}` : undefined;\n\n const options: WgetOptions = {\n proxy: {\n port: a.port ? parseInt(a.port, 10) : 80,\n protocol: a.protocol.replace(\":\", \"\"),\n host: a.hostname ?? \"\",\n proxyAuth: auth\n }\n };\n warningLog(chalk.green(\"- using proxy \"), proxy);\n warningLog(options);\n return options;\n }\n return {};\n}\n\nasync function execute(cmd: string, cwd?: string): Promise<ExecuteResult> {\n let output = \"\";\n\n // xx cwd = cwd ? {cwd: cwd} : {};\n const options = {\n cwd,\n windowsHide: true\n };\n\n return await new Promise<ExecuteResult>((resolve, reject) => {\n const child = child_process.exec(\n cmd,\n options,\n (err: child_process.ExecException | null /*, stdout: string, stderr: string*/) => {\n const exitCode = err === null ? 0 : err.code || 1;\n if (err) reject(err);\n else {\n resolve({ exitCode, output });\n }\n }\n );\n\n const stream1 = byline(child.stdout as Readable);\n stream1.on(\"data\", (line: string) => {\n output += `${line}\\n`;\n // istanbul ignore next\n if (doDebug) {\n process.stdout.write(` stdout ${chalk.yellow(line)}\\n`);\n }\n });\n });\n}\n\nfunction quote(str: string): string {\n return `\"${str.replace(/\\\\/g, \"/\")}\"`;\n}\n\nfunction is_expected_openssl_version(strVersion: string): boolean {\n return !!strVersion.match(/OpenSSL 1|3/);\n}\n\nasync function getopensslExecPath(): Promise<string> {\n let result1: ExecuteResult | undefined;\n try {\n result1 = await execute(\"which openssl\");\n } catch (err) {\n warningLog(\"warning: \", (err as Error).message);\n throw new Error(\"Cannot find openssl\");\n }\n\n const exitCode = result1?.exitCode;\n const output = result1?.output;\n\n if (exitCode !== 0) {\n warningLog(chalk.yellow(\" it seems that \") + chalk.cyan(\"openssl\") + chalk.yellow(\" is not installed on your computer \"));\n warningLog(chalk.yellow(\"Please install it before running this programs\"));\n throw new Error(\"Cannot find openssl\");\n }\n const opensslExecPath = output.replace(/\\n\\r/g, \"\").trim();\n return opensslExecPath;\n}\nexport async function check_system_openssl_version(): Promise<string> {\n const opensslExecPath = await getopensslExecPath();\n\n // tslint:disable-next-line:variable-name\n const q_opensslExecPath = quote(opensslExecPath);\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(` OpenSSL found in : ${chalk.yellow(opensslExecPath)}`);\n }\n // ------------------------ now verify that openssl version is the correct one\n const result = await execute(`${q_opensslExecPath} version`);\n\n const exitCode = result?.exitCode;\n const output = result?.output;\n\n const version = output.trim();\n\n const versionOK = exitCode === 0 && is_expected_openssl_version(version);\n if (!versionOK) {\n let message =\n chalk.whiteBright(\"Warning !!!!!!!!!!!! \") +\n \"\\nyour version of openssl is \" +\n version +\n \". It doesn't match the expected version\";\n\n if (process.platform === \"darwin\") {\n message +=\n chalk.cyan(\"\\nplease refer to :\") +\n chalk.yellow(\" https://github.com/node-opcua/node-opcua/\" + \"wiki/installing-node-opcua-or-node-red-on-MacOS\");\n }\n\n console.log(message);\n }\n return output;\n}\n\nasync function install_and_check_win32_openssl_version(): Promise<string> {\n const downloadFolder = path.join(os.tmpdir(), \".\");\n\n function get_openssl_folder_win32(): string {\n if (process.env.LOCALAPPDATA) {\n const userProgramFolder = path.join(process.env.LOCALAPPDATA, \"Programs\");\n if (fs.existsSync(userProgramFolder)) {\n return path.join(userProgramFolder, \"openssl\");\n }\n }\n return path.join(process.cwd(), \"openssl\");\n }\n\n function get_openssl_exec_path_win32(): string {\n const opensslFolder = get_openssl_folder_win32();\n return path.join(opensslFolder, \"openssl.exe\");\n }\n\n async function check_openssl_win32(): Promise<{ opensslOk?: boolean; version?: string }> {\n const opensslExecPath = get_openssl_exec_path_win32();\n\n const exists = fs.existsSync(opensslExecPath);\n if (!exists) {\n warningLog(\"checking presence of \", opensslExecPath);\n warningLog(chalk.red(\" cannot find file \") + opensslExecPath);\n return {\n opensslOk: false,\n version: `cannot find file ${opensslExecPath}`\n };\n } else {\n // tslint:disable-next-line:variable-name\n const q_openssl_exe_path = quote(opensslExecPath);\n const cwd = \".\";\n\n const { exitCode, output } = await execute(`${q_openssl_exe_path} version`, cwd);\n const version = output.trim();\n // istanbul ignore next\n\n if (doDebug) {\n warningLog(\" Version = \", version);\n }\n return {\n opensslOk: exitCode === 0 && is_expected_openssl_version(version),\n version\n };\n }\n }\n\n /**\n * detect whether windows OS is a 64 bits or 32 bits\n * http://ss64.com/nt/syntax-64bit.html\n * http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx\n * @return {number}\n */\n function win32or64(): 32 | 64 {\n if (process.env.PROCESSOR_ARCHITECTURE === \"x86\" && process.env.PROCESSOR_ARCHITEW6432) {\n return 64;\n }\n\n if (process.env.PROCESSOR_ARCHITECTURE === \"AMD64\") {\n return 64;\n }\n\n // check if we are running node x32 on a x64 arch\n if (process.env.CURRENT_CPU === \"x64\") {\n return 64;\n }\n return 32;\n }\n\n async function download_openssl(): Promise<{ downloadedFile: string }> {\n // const url = (win32or64() === 64 )\n // ? \"http://indy.fulgan.com/SSL/openssl-1.0.2o-x64_86-win64.zip\"\n // : \"http://indy.fulgan.com/SSL/openssl-1.0.2o-i386-win32.zip\"\n // ;\n const url =\n win32or64() === 64\n ? \"https://github.com/node-opcua/node-opcua-pki/releases/download/2.14.2/openssl-1.0.2u-x64_86-win64.zip\"\n : \"https://github.com/node-opcua/node-opcua-pki/releases/download/2.14.2/openssl-1.0.2u-i386-win32.zip\";\n // the zip file\n const outputFilename = path.join(downloadFolder, path.basename(url));\n\n warningLog(`downloading ${chalk.yellow(url)} to ${outputFilename}`);\n\n if (fs.existsSync(outputFilename)) {\n return { downloadedFile: outputFilename };\n }\n const options = makeOptions();\n const bar = new ProgressBar(chalk.cyan(\"[:bar]\") + chalk.cyan(\" :percent \") + chalk.white(\":etas\"), {\n complete: \"=\",\n incomplete: \" \",\n total: 100,\n width: 100\n });\n\n return await new Promise((resolve, reject) => {\n const download = wget.download(url, outputFilename, options);\n download.on(\"error\", (err: Error) => {\n warningLog(err);\n setImmediate(() => {\n reject(err);\n });\n });\n download.on(\"end\", (output: string) => {\n // istanbul ignore next\n if (doDebug) {\n warningLog(output);\n }\n // warningLog(\"done ...\");\n resolve({ downloadedFile: outputFilename });\n });\n download.on(\"progress\", (progress: number) => {\n bar.update(progress);\n });\n });\n }\n\n async function unzip_openssl(zipFilename: string) {\n const opensslFolder = get_openssl_folder_win32();\n\n const zipFile = await new Promise<yauzl.ZipFile>((resolve, reject) => {\n yauzl.open(zipFilename, { lazyEntries: true }, (err?: Error | null, zipfile?: yauzl.ZipFile) => {\n if (err) {\n reject(err);\n } else {\n if (!zipfile) {\n reject(new Error(\"zipfile is null\"));\n } else {\n resolve(zipfile);\n }\n }\n });\n });\n\n zipFile.readEntry();\n\n await new Promise<void>((resolve, reject) => {\n zipFile.on(\"end\", (err?: Error) => {\n setImmediate(() => {\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"unzip done\");\n }\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n\n zipFile.on(\"entry\", (entry: yauzl.Entry) => {\n zipFile.openReadStream(entry, (err?: Error | null, readStream?: Readable) => {\n if (err) {\n return reject(err);\n }\n\n const file = path.join(opensslFolder, entry.fileName);\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(\" unzipping :\", file);\n }\n\n const writeStream = fs.createWriteStream(file, \"binary\");\n // ensure parent directory exists\n readStream?.pipe(writeStream);\n\n writeStream.on(\"close\", () => {\n zipFile.readEntry();\n });\n });\n });\n });\n }\n\n const opensslFolder = get_openssl_folder_win32();\n const opensslExecPath = get_openssl_exec_path_win32();\n\n if (!fs.existsSync(opensslFolder)) {\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"creating openssl_folder\", opensslFolder);\n }\n fs.mkdirSync(opensslFolder);\n }\n\n const { opensslOk, version: _version } = await check_openssl_win32();\n\n if (!opensslOk) {\n warningLog(chalk.yellow(\"openssl seems to be missing and need to be installed\"));\n const { downloadedFile } = await download_openssl();\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"deflating \", chalk.yellow(downloadedFile));\n }\n await unzip_openssl(downloadedFile);\n\n const opensslExists = !!fs.existsSync(opensslExecPath);\n\n // istanbul ignore next\n if (doDebug) {\n warningLog(\"verifying \", opensslExists, opensslExists ? chalk.green(\"OK \") : chalk.red(\" Error\"), opensslExecPath);\n }\n\n const _opensslExecPath2 = await check_openssl_win32();\n return opensslExecPath;\n } else {\n // istanbul ignore next\n if (doDebug) {\n warningLog(chalk.green(\"openssl is already installed and have the expected version.\"));\n }\n return opensslExecPath;\n }\n}\n\n/**\n *\n * return path to the openssl executable\n */\nexport async function install_prerequisite(): Promise<string> {\n // istanbul ignore else\n if (process.platform !== \"win32\") {\n return await check_system_openssl_version();\n } else {\n return await install_and_check_win32_openssl_version();\n }\n}\n\nexport async function get_openssl_exec_path(): Promise<string> {\n if (process.platform === \"win32\") {\n const opensslExecPath = await install_prerequisite();\n if (!fs.existsSync(opensslExecPath)) {\n throw new Error(`internal error cannot find ${opensslExecPath}`);\n }\n return opensslExecPath;\n } else {\n return \"openssl\";\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// tslint:disable:no-console\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { Filename } from \"../common\";\nimport { quote } from \"../common\";\nimport { makePath } from \"../common2\";\nimport { g_config } from \"../config\";\nimport { getEnv, getEnvironmentVarNames } from \"./_env\";\nimport { type ExecuteOptions, execute_openssl } from \"./execute_openssl\";\n\nfunction openssl_require2DigitYearInDate() {\n // istanbul ignore next\n if (!g_config.opensslVersion) {\n throw new Error(\n \"openssl_require2DigitYearInDate : openssl version is not known:\" + \" please call ensure_openssl_installed()\"\n );\n }\n return g_config.opensslVersion.match(/OpenSSL 0\\.9/);\n}\n\ng_config.opensslVersion = \"\";\n\nlet _counter = 0;\n\nexport function generateStaticConfig(configPath: string, options?: ExecuteOptions) {\n const prePath = options?.cwd || \"\";\n\n const originalFilename = !path.isAbsolute(configPath) ? path.join(prePath, configPath) : configPath;\n let staticConfig = fs.readFileSync(originalFilename, { encoding: \"utf8\" });\n for (const envVar of getEnvironmentVarNames()) {\n staticConfig = staticConfig.replace(new RegExp(envVar.pattern, \"gi\"), getEnv(envVar.key));\n }\n const staticConfigPath = `${configPath}.${process.pid}-${_counter++}.tmp`;\n const temporaryConfigPath = !path.isAbsolute(configPath) ? path.join(prePath, staticConfigPath) : staticConfigPath;\n fs.writeFileSync(temporaryConfigPath, staticConfig);\n if (options?.cwd) {\n return path.relative(options.cwd, temporaryConfigPath);\n } else {\n return temporaryConfigPath;\n }\n}\n\nconst q = quote;\nconst n = makePath;\n\n/**\n * calculate the public key from private key\n * openssl rsa -pubout -in private_key.pem\n *\n * @method getPublicKeyFromPrivateKey\n * @param privateKeyFilename: the existing file with the private key\n * @param publicKeyFilename: the file where to store the public key\n */\nexport async function getPublicKeyFromPrivateKey(privateKeyFilename: string, publicKeyFilename: string): Promise<void> {\n assert(fs.existsSync(privateKeyFilename));\n await execute_openssl(`rsa -pubout -in ${q(n(privateKeyFilename))} -out ${q(n(publicKeyFilename))}`, {});\n}\n\n/**\n * extract public key from a certificate\n * openssl x509 -pubkey -in certificate.pem -nottext\n *\n * @method getPublicKeyFromCertificate\n * @param certificateFilename\n * @param publicKeyFilename\n */\nexport async function getPublicKeyFromCertificate(certificateFilename: string, publicKeyFilename: string) {\n assert(fs.existsSync(certificateFilename));\n await execute_openssl(`x509 -pubkey -in ${q(n(certificateFilename))} > ${q(n(publicKeyFilename))}`, {});\n}\nexport function x509Date(date?: Date): string {\n date = date || new Date();\n const Y = date.getUTCFullYear();\n const M = date.getUTCMonth() + 1;\n const D = date.getUTCDate();\n const h = date.getUTCHours();\n const m = date.getUTCMinutes();\n const s = date.getUTCSeconds();\n\n function w(s: string | number, l: number): string {\n return `${s}`.padStart(l, \"0\");\n }\n\n if (openssl_require2DigitYearInDate()) {\n // for example: on MacOS , where openssl 0.98 is installed by default\n return `${w(Y, 2) + w(M, 2) + w(D, 2) + w(h, 2) + w(m, 2) + w(s, 2)}Z`;\n } else {\n // for instance when openssl version is greater than 1.0.0\n return `${w(Y, 4) + w(M, 2) + w(D, 2) + w(h, 2) + w(m, 2) + w(s, 2)}Z`;\n }\n}\n\n/**\n * @param certificate - the certificate file in PEM format, file must exist\n */\nexport async function dumpCertificate(certificate: Filename): Promise<string> {\n assert(fs.existsSync(certificate));\n return await execute_openssl(`x509 -in ${q(n(certificate))} -text -noout`, {});\n}\n\nexport async function toDer(certificatePem: string): Promise<string> {\n assert(fs.existsSync(certificatePem));\n const certificateDer = certificatePem.replace(\".pem\", \".der\");\n return await execute_openssl(`x509 -outform der -in ${certificatePem} -out ${certificateDer}`, {});\n}\n\nexport async function fingerprint(certificatePem: string): Promise<string> {\n // openssl x509 -in my_certificate.pem -hash -dates -noout -fingerprint\n assert(fs.existsSync(certificatePem));\n return await execute_openssl(`x509 -fingerprint -noout -in ${certificatePem}`, {});\n}\n","const config =\n \"#.........DO NOT MODIFY BY HAND .........................\\n\" +\n \"[ ca ]\\n\" +\n \"default_ca = CA_default\\n\" +\n \"[ CA_default ]\\n\" +\n \"dir = %%ROOT_FOLDER%% # the main CA folder\\n\" +\n \"certs = $dir/certs # where to store certificates\\n\" +\n \"new_certs_dir = $dir/certs #\\n\" +\n \"database = $dir/index.txt # the certificate database\\n\" +\n \"serial = $dir/serial # the serial number counter\\n\" +\n \"certificate = $dir/public/cacert.pem # The root CA certificate\\n\" +\n \"private_key = $dir/private/cakey.pem # the CA private key\\n\" +\n \"x509_extensions = usr_cert #\\n\" +\n \"default_days = 3650 # default validity : 10 years\\n\" +\n \"\\n\" +\n \"# default_md = sha1\\n\" +\n \"\\n\" +\n \"default_md = sha256 # The default digest algorithm\\n\" +\n \"\\n\" +\n \"preserve = no\\n\" +\n \"policy = policy_match\\n\" +\n \"# randfile = $dir/random.rnd\\n\" +\n \"# default_startdate = YYMMDDHHMMSSZ\\n\" +\n \"# default_enddate = YYMMDDHHMMSSZ\\n\" +\n \"crl_dir = $dir/crl\\n\" +\n \"crl_extensions = crl_ext\\n\" +\n \"crl = $dir/revocation_list.crl # the Revocation list\\n\" +\n \"crlnumber = $dir/crlnumber # CRL number file\\n\" +\n \"default_crl_days = 30\\n\" +\n \"default_crl_hours = 24\\n\" +\n \"#msie_hack\\n\" +\n \"\\n\" +\n \"[ policy_match ]\\n\" +\n \"countryName = optional\\n\" +\n \"stateOrProvinceName = optional\\n\" +\n \"localityName = optional\\n\" +\n \"organizationName = optional\\n\" +\n \"organizationalUnitName = optional\\n\" +\n \"commonName = optional\\n\" +\n \"emailAddress = optional\\n\" +\n \"\\n\" +\n \"[ req ]\\n\" +\n \"default_bits = 4096 # Size of keys\\n\" +\n \"default_keyfile = key.pem # name of generated keys\\n\" +\n \"distinguished_name = req_distinguished_name\\n\" +\n \"attributes = req_attributes\\n\" +\n \"x509_extensions = v3_ca\\n\" +\n \"#input_password\\n\" +\n \"#output_password\\n\" +\n \"string_mask = nombstr # permitted characters\\n\" +\n \"req_extensions = v3_req\\n\" +\n \"\\n\" +\n \"[ req_distinguished_name ]\\n\" +\n \"\\n\" +\n \"#0 countryName = Country Name (2 letter code)\\n\" +\n \"# countryName_default = FR\\n\" +\n \"# countryName_min = 2\\n\" +\n \"# countryName_max = 2\\n\" +\n \"# stateOrProvinceName = State or Province Name (full name)\\n\" +\n \"# stateOrProvinceName_default = Ile de France\\n\" +\n \"# localityName = Locality Name (city, district)\\n\" +\n \"# localityName_default = Paris\\n\" +\n \"organizationName = Organization Name (company)\\n\" +\n \"organizationName_default = NodeOPCUA\\n\" +\n \"# organizationalUnitName = Organizational Unit Name (department, division)\\n\" +\n \"# organizationalUnitName_default = R&D\\n\" +\n \"commonName = Common Name (hostname, FQDN, IP, or your name)\\n\" +\n \"commonName_max = 256\\n\" +\n \"commonName_default = NodeOPCUA\\n\" +\n \"# emailAddress = Email Address\\n\" +\n \"# emailAddress_max = 40\\n\" +\n \"# emailAddress_default = node-opcua (at) node-opcua (dot) com\\n\" +\n \"\\n\" +\n \"[ req_attributes ]\\n\" +\n \"#challengePassword = A challenge password\\n\" +\n \"#challengePassword_min = 4\\n\" +\n \"#challengePassword_max = 20\\n\" +\n \"#unstructuredName = An optional company name\\n\" +\n \"[ usr_cert ]\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid,issuer:always\\n\" +\n \"#authorityKeyIdentifier = keyid\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"# issuerAltName = issuer:copy\\n\" +\n \"nsComment = ''OpenSSL Generated Certificate''\\n\" +\n \"#nsCertType = client, email, objsign for ''everything including object signing''\\n\" +\n \"#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem\\n\" +\n \"#nsBaseUrl =\\n\" +\n \"#nsRenewalUrl =\\n\" +\n \"#nsCaPolicyUrl =\\n\" +\n \"#nsSslServerName =\\n\" +\n \"keyUsage = critical, digitalSignature, nonRepudiation,\" +\n \" keyEncipherment, dataEncipherment, keyAgreement, keyCertSign\\n\" +\n \"extendedKeyUsage = critical,serverAuth ,clientAuth\\n\" +\n \"\\n\" +\n \"[ v3_req ]\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement\\n\" +\n \"extendedKeyUsage = critical,serverAuth ,clientAuth\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n 'nsComment = \"CA Generated by Node-OPCUA Certificate utility using openssl\"\\n' +\n \"[ v3_ca ]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid:always,issuer:always\\n\" +\n \"# authorityKeyIdentifier = keyid\\n\" +\n \"basicConstraints = CA:TRUE\\n\" +\n \"keyUsage = critical, cRLSign, keyCertSign\\n\" +\n 'nsComment = \"CA Certificate generated by Node-OPCUA Certificate utility using openssl\"\\n' +\n \"#nsCertType = sslCA, emailCA\\n\" +\n \"#subjectAltName = email:copy\\n\" +\n \"#issuerAltName = issuer:copy\\n\" +\n \"#obj = DER:02:03\\n\" +\n \"crlDistributionPoints = @crl_info\\n\" +\n \"[ crl_info ]\\n\" +\n \"URI.0 = http://localhost:8900/crl.pem\\n\" +\n \"[ v3_selfsigned]\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement\\n\" +\n \"extendedKeyUsage = critical,serverAuth ,clientAuth\\n\" +\n 'nsComment = \"Self-signed certificate, generated by NodeOPCUA\"\\n' +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"\\n\" +\n \"[ crl_ext ]\\n\" +\n \"#issuerAltName = issuer:copy\\n\" +\n \"authorityKeyIdentifier = keyid:always,issuer:always\\n\" +\n \"#authorityInfoAccess = @issuer_info\";\n\nexport default config;\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n// Error.stackTraceLimit = Infinity;\n// tslint:disable:variable-name\n// tslint:disable:no-console\n// tslint:disable:object-literal-sort-keys\n// tslint:disable:no-shadowed-variable\n\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport { CertificatePurpose, generatePrivateKeyFile, Subject, type SubjectOptions } from \"node-opcua-crypto\";\n\nimport { makeApplicationUrn } from \"../misc/applicationurn\";\nimport { extractFullyQualifiedDomainName, getFullyQualifiedDomainName } from \"../misc/hostname\";\nimport { CertificateManager, type CreateSelfSignCertificateParam1 } from \"../pki/certificate_manager\";\nimport {\n type CreateCertificateSigningRequestWithConfigOptions,\n debugLog,\n displayChapter,\n displaySubtitle,\n displayTitle,\n type Filename,\n g_config,\n type KeySize,\n makePath,\n mkdirRecursiveSync,\n warningLog\n} from \"../toolbox\";\nimport {\n createCertificateSigningRequestWithOpenSSL,\n dumpCertificate,\n ensure_openssl_installed,\n fingerprint,\n getPublicKeyFromPrivateKey,\n setEnv,\n toDer\n} from \"../toolbox/with_openssl\";\nimport { CertificateAuthority, defaultSubject } from \"./certificate_authority\";\n\nconst epilog = \"Copyright (c) sterfive - node-opcua - 2017-2026\";\n\n// ------------------------------------------------- some useful dates\nfunction get_offset_date(date: Date, nbDays: number): Date {\n const d = new Date(date.getTime());\n d.setDate(d.getDate() + nbDays);\n return d;\n}\n\nconst today = new Date();\nconst yesterday = get_offset_date(today, -1);\nconst two_years_ago = get_offset_date(today, -2 * 365);\nconst next_year = get_offset_date(today, 365);\n\ninterface LocalConfig {\n CAFolder?: string;\n PKIFolder?: string;\n\n keySize?: KeySize;\n\n subject?: SubjectOptions | string;\n\n certificateDir?: Filename;\n\n privateKey?: Filename;\n\n applicationUri?: string;\n\n outputFile?: string;\n\n altNames?: string[];\n dns?: string[];\n ip?: string[];\n\n startDate?: Date;\n validity?: number;\n}\n\nlet gLocalConfig: LocalConfig = {};\n\nlet g_certificateAuthority: CertificateAuthority; // the Certificate Authority\n\n/***\n *\n *\n * prerequisites :\n * g_config.CAFolder : the folder of the CA\n */\nasync function construct_CertificateAuthority(subject: string) {\n // verify that g_config file has been loaded\n assert(typeof gLocalConfig.CAFolder === \"string\", \"expecting a CAFolder in config\");\n assert(typeof gLocalConfig.keySize === \"number\", \"expecting a keySize in config\");\n\n if (!g_certificateAuthority) {\n g_certificateAuthority = new CertificateAuthority({\n keySize: gLocalConfig.keySize,\n location: gLocalConfig.CAFolder,\n subject\n });\n await g_certificateAuthority.initialize();\n }\n}\n\nlet certificateManager: CertificateManager; // the Certificate Manager\n/***\n *\n *\n * prerequisites :\n * g_config.PKIFolder : the folder of the PKI\n */\nasync function construct_CertificateManager() {\n assert(typeof gLocalConfig.PKIFolder === \"string\", \"expecting a PKIFolder in config\");\n\n if (!certificateManager) {\n certificateManager = new CertificateManager({\n keySize: gLocalConfig.keySize,\n location: gLocalConfig.PKIFolder\n });\n await certificateManager.initialize();\n }\n}\n\nfunction _displayConfig(config: { [key: string]: { toString: () => string } }) {\n function w(str: string, l: number): string {\n return `${str} `.substring(0, l);\n }\n\n warningLog(chalk.yellow(\" configuration = \"));\n\n for (const [key, value] of Object.entries(config)) {\n warningLog(` ${chalk.yellow(w(key, 30))} : ${chalk.cyan(value.toString())}`);\n }\n}\n\nfunction default_template_content(): string {\n // istanbul ignore next\n if ((process as unknown as { pkg?: { entrypoint: string } }).pkg?.entrypoint) {\n // we are using PKG compiled package !\n\n // warningLog(\"___filename\", __filename);\n // warningLog(\"__dirname\", __dirname);\n // warningLog(\"process.pkg.entrypoint\", (process as unknown as IReadConfigurationOpts).pkg.entrypoint);\n const a = fs.readFileSync(path.join(__dirname, \"../../bin/pki_config.example.js\"), \"utf8\");\n return a;\n }\n function find_default_config_template() {\n const rootFolder = find_module_root_folder();\n\n // Note: we use a hardcoded config filename here because after tsup bundling,\n // __filename points to the bundle file (e.g., \"index.mjs\") rather than the\n // original source file, making dynamic name construction unreliable.\n const configName = \"pki_config.example.js\";\n\n let default_config_template = path.join(rootFolder, \"bin\", configName);\n\n if (!fs.existsSync(default_config_template)) {\n default_config_template = path.join(__dirname, \"..\", configName);\n\n if (!fs.existsSync(default_config_template)) {\n default_config_template = path.join(__dirname, `../bin/${configName}`);\n }\n }\n return default_config_template;\n }\n const default_config_template = find_default_config_template();\n assert(fs.existsSync(default_config_template));\n const default_config_template_content = fs.readFileSync(default_config_template, \"utf8\");\n return default_config_template_content;\n}\n\n/**\n *\n */\nfunction find_module_root_folder() {\n let rootFolder = path.join(__dirname);\n\n for (let i = 0; i < 4; i++) {\n if (fs.existsSync(path.join(rootFolder, \"package.json\"))) {\n return rootFolder;\n }\n rootFolder = path.join(rootFolder, \"..\");\n }\n\n assert(fs.existsSync(path.join(rootFolder, \"package.json\")), \"root folder must have a package.json file\");\n return rootFolder;\n}\n\ninterface IReadConfigurationOpts {\n root: string;\n silent?: boolean;\n subject?: string;\n CAFolder?: string;\n PKIFolder?: string;\n privateKey?: string;\n applicationUri?: string;\n output?: string;\n altNames?: string;\n dns?: string;\n ip?: string;\n keySize?: KeySize;\n validity?: number;\n}\n\n/* eslint complexity:off, max-statements:off */\nasync function readConfiguration(argv: IReadConfigurationOpts) {\n if (argv.silent) {\n g_config.silent = true;\n } else {\n g_config.silent = false;\n }\n\n const fqdn = await extractFullyQualifiedDomainName();\n const hostname = os.hostname();\n let certificateDir: string;\n\n function performSubstitution(str: string): string {\n str = str.replace(\"{CWD}\", process.cwd());\n if (certificateDir) {\n str = str.replace(\"{root}\", certificateDir);\n }\n if (gLocalConfig?.PKIFolder) {\n str = str.replace(\"{PKIFolder}\", gLocalConfig.PKIFolder);\n }\n str = str.replace(\"{hostname}\", hostname);\n str = str.replace(\"%FQDN%\", fqdn);\n return str;\n }\n\n function prepare(file: Filename): Filename {\n const tmp = path.resolve(performSubstitution(file));\n return makePath(tmp);\n }\n\n // ------------------------------------------------------------------------------------------------------------\n certificateDir = argv.root;\n assert(typeof certificateDir === \"string\");\n\n certificateDir = prepare(certificateDir);\n mkdirRecursiveSync(certificateDir);\n assert(fs.existsSync(certificateDir));\n\n // ------------------------------------------------------------------------------------------------------------\n const default_config = path.join(certificateDir, \"config.js\");\n\n if (!fs.existsSync(default_config)) {\n // copy\n debugLog(chalk.yellow(\" Creating default g_config file \"), chalk.cyan(default_config));\n const default_config_template_content = default_template_content();\n fs.writeFileSync(default_config, default_config_template_content);\n } else {\n debugLog(chalk.yellow(\" using g_config file \"), chalk.cyan(default_config));\n }\n if (!fs.existsSync(default_config)) {\n debugLog(chalk.redBright(\" cannot find config file \", default_config));\n }\n\n // see http://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean\n // set random file to be random.rnd in the same folder as the g_config file\n const defaultRandomFile = path.join(path.dirname(default_config), \"random.rnd\");\n setEnv(\"RANDFILE\", defaultRandomFile);\n\n /* eslint global-require: 0*/\n const _require = createRequire(__filename);\n gLocalConfig = _require(default_config);\n\n gLocalConfig.subject = new Subject(gLocalConfig.subject || \"\");\n\n // if subject is provided on the command line , it has hight priority\n if (argv.subject) {\n gLocalConfig.subject = new Subject(argv.subject);\n }\n\n // istanbul ignore next\n if (!gLocalConfig.subject.commonName) {\n throw new Error(\"subject must have a Common Name\");\n }\n\n gLocalConfig.certificateDir = certificateDir;\n\n // ------------------------------------------------------------------------------------------------------------\n let CAFolder = argv.CAFolder || path.join(certificateDir, \"CA\");\n CAFolder = prepare(CAFolder);\n gLocalConfig.CAFolder = CAFolder;\n\n // ------------------------------------------------------------------------------------------------------------\n gLocalConfig.PKIFolder = path.join(gLocalConfig.certificateDir, \"PKI\");\n if (argv.PKIFolder) {\n gLocalConfig.PKIFolder = prepare(argv.PKIFolder);\n }\n gLocalConfig.PKIFolder = prepare(gLocalConfig.PKIFolder);\n if (argv.privateKey) {\n gLocalConfig.privateKey = prepare(argv.privateKey);\n }\n\n if (argv.applicationUri) {\n gLocalConfig.applicationUri = performSubstitution(argv.applicationUri);\n }\n\n if (argv.output) {\n gLocalConfig.outputFile = argv.output;\n }\n\n gLocalConfig.altNames = [];\n if (argv.altNames) {\n gLocalConfig.altNames = argv.altNames.split(\";\");\n }\n gLocalConfig.dns = [getFullyQualifiedDomainName()];\n if (argv.dns) {\n gLocalConfig.dns = argv.dns.split(\",\").map(performSubstitution);\n }\n gLocalConfig.ip = [];\n if (argv.ip) {\n gLocalConfig.ip = argv.ip.split(\",\");\n }\n if (argv.keySize) {\n const v = argv.keySize;\n if (v !== 1024 && v !== 2048 && v !== 3072 && v !== 4096) {\n throw new Error(`invalid keysize specified ${v} should be 1024,2048,3072 or 4096`);\n }\n gLocalConfig.keySize = argv.keySize;\n }\n\n if (argv.validity) {\n gLocalConfig.validity = argv.validity;\n }\n // xx displayConfig(g_config);\n // ------------------------------------------------------------------------------------------------------------\n}\n\nasync function createDefaultCertificate(\n base_name: string,\n prefix: string,\n key_length: KeySize,\n applicationUri: string,\n dev: boolean\n) {\n // possible key length in bits\n assert(key_length === 1024 || key_length === 2048 || key_length === 3072 || key_length === 4096);\n\n const private_key_file = makePath(base_name, `${prefix}key_${key_length}.pem`);\n const public_key_file = makePath(base_name, `${prefix}public_key_${key_length}.pub`);\n const certificate_file = makePath(base_name, `${prefix}cert_${key_length}.pem`);\n const certificate_file_outofdate = makePath(base_name, `${prefix}cert_${key_length}_outofdate.pem`);\n const certificate_file_not_active_yet = makePath(base_name, `${prefix}cert_${key_length}_not_active_yet.pem`);\n const certificate_revoked = makePath(base_name, `${prefix}cert_${key_length}_revoked.pem`);\n const self_signed_certificate_file = makePath(base_name, `${prefix}selfsigned_cert_${key_length}.pem`);\n\n const fqdn = getFullyQualifiedDomainName();\n const hostname = os.hostname();\n const dns: string[] = [\n // for conformance reason, localhost shall not be present in the DNS field of COP\n // ***FORBIDEN** \"localhost\",\n getFullyQualifiedDomainName()\n ];\n if (hostname !== fqdn) {\n dns.push(hostname);\n }\n\n const ip: string[] = [];\n\n async function createCertificateIfNotExist(\n certificate: Filename,\n private_key: Filename,\n applicationUri: string,\n startDate: Date,\n validity: number\n ): Promise<string> {\n // istanbul ignore next\n if (fs.existsSync(certificate)) {\n warningLog(chalk.yellow(\" certificate\"), chalk.cyan(certificate), chalk.yellow(\" already exists => skipping\"));\n return \"\";\n } else {\n return await createCertificate(certificate, private_key, applicationUri, startDate, validity);\n }\n }\n\n async function createCertificate(\n certificate: Filename,\n privateKey: Filename,\n applicationUri: string,\n startDate: Date,\n validity: number\n ): Promise<string> {\n const certificateSigningRequestFile = `${certificate}.csr`;\n\n const configFile = makePath(base_name, \"../certificates/PKI/own/openssl.cnf\");\n\n const dns = [os.hostname()];\n const ip = [\"127.0.0.1\"];\n\n const params: CreateCertificateSigningRequestWithConfigOptions = {\n applicationUri,\n privateKey,\n rootDir: \".\",\n configFile,\n dns,\n ip,\n purpose: CertificatePurpose.ForApplication\n };\n\n // create CSR\n await createCertificateSigningRequestWithOpenSSL(certificateSigningRequestFile, params);\n\n return await g_certificateAuthority.signCertificateRequest(certificate, certificateSigningRequestFile, {\n applicationUri,\n dns,\n ip,\n startDate,\n validity\n });\n }\n\n async function createSelfSignedCertificate(\n certificate: Filename,\n private_key: Filename,\n applicationUri: string,\n startDate: Date,\n validity: number\n ) {\n await g_certificateAuthority.createSelfSignedCertificate(certificate, private_key, {\n applicationUri,\n dns,\n ip,\n startDate,\n validity\n });\n }\n\n async function revoke_certificate(certificate: Filename) {\n await g_certificateAuthority.revokeCertificate(certificate, {});\n }\n\n async function createPrivateKeyIfNotExist(privateKey: Filename, keyLength: KeySize) {\n if (fs.existsSync(privateKey)) {\n warningLog(chalk.yellow(\" privateKey\"), chalk.cyan(privateKey), chalk.yellow(\" already exists => skipping\"));\n return;\n } else {\n await generatePrivateKeyFile(privateKey, keyLength);\n }\n }\n\n displaySubtitle(` create private key :${private_key_file}`);\n\n await createPrivateKeyIfNotExist(private_key_file, key_length);\n displaySubtitle(` extract public key ${public_key_file} from private key `);\n await getPublicKeyFromPrivateKey(private_key_file, public_key_file);\n displaySubtitle(` create Certificate ${certificate_file}`);\n\n await createCertificateIfNotExist(certificate_file, private_key_file, applicationUri, yesterday, 365);\n\n displaySubtitle(` create self signed Certificate ${self_signed_certificate_file}`);\n\n if (fs.existsSync(self_signed_certificate_file)) {\n // self_signed certificate already exists\n return;\n }\n await createSelfSignedCertificate(self_signed_certificate_file, private_key_file, applicationUri, yesterday, 365);\n\n if (dev) {\n await createCertificateIfNotExist(certificate_file_outofdate, private_key_file, applicationUri, two_years_ago, 365);\n\n await createCertificateIfNotExist(certificate_file_not_active_yet, private_key_file, applicationUri, next_year, 365);\n\n if (!fs.existsSync(certificate_revoked)) {\n // self_signed certificate already exists\n const certificate = await createCertificateIfNotExist(\n certificate_revoked,\n private_key_file,\n `${applicationUri}Revoked`, // make sure we used a uniq URI here\n yesterday,\n 365\n );\n warningLog(\" certificate to revoke => \", certificate);\n revoke_certificate(certificate_revoked);\n }\n }\n}\n\nasync function wrap(func: () => Promise<void>) {\n try {\n await func();\n } catch (err) {\n console.log((err as Error).message);\n }\n}\n\nasync function create_default_certificates(dev: boolean) {\n assert(gLocalConfig);\n const base_name = gLocalConfig.certificateDir || \"\";\n assert(fs.existsSync(base_name));\n\n let clientURN: string;\n let serverURN: string;\n let discoveryServerURN: string;\n wrap(async () => {\n await extractFullyQualifiedDomainName();\n const hostname = os.hostname();\n const fqdn = getFullyQualifiedDomainName();\n warningLog(chalk.yellow(\" hostname = \"), chalk.cyan(hostname));\n warningLog(chalk.yellow(\" fqdn = \"), chalk.cyan(fqdn));\n clientURN = makeApplicationUrn(hostname, \"NodeOPCUA-Client\");\n serverURN = makeApplicationUrn(hostname, \"NodeOPCUA-Server\");\n discoveryServerURN = makeApplicationUrn(hostname, \"NodeOPCUA-DiscoveryServer\");\n\n displayTitle(\"Create Application Certificate for Server & its private key\");\n await createDefaultCertificate(base_name, \"client_\", 1024, clientURN, dev);\n await createDefaultCertificate(base_name, \"client_\", 2048, clientURN, dev);\n await createDefaultCertificate(base_name, \"client_\", 3072, clientURN, dev);\n await createDefaultCertificate(base_name, \"client_\", 4096, clientURN, dev);\n\n displayTitle(\"Create Application Certificate for Client & its private key\");\n await createDefaultCertificate(base_name, \"server_\", 1024, serverURN, dev);\n await createDefaultCertificate(base_name, \"server_\", 2048, serverURN, dev);\n await createDefaultCertificate(base_name, \"server_\", 3072, serverURN, dev);\n await createDefaultCertificate(base_name, \"server_\", 4096, serverURN, dev);\n\n displayTitle(\"Create Application Certificate for DiscoveryServer & its private key\");\n await createDefaultCertificate(base_name, \"discoveryServer_\", 1024, discoveryServerURN, dev);\n await createDefaultCertificate(base_name, \"discoveryServer_\", 2048, discoveryServerURN, dev);\n await createDefaultCertificate(base_name, \"discoveryServer_\", 3072, discoveryServerURN, dev);\n await createDefaultCertificate(base_name, \"discoveryServer_\", 4096, discoveryServerURN, dev);\n });\n}\n\nasync function createDefaultCertificates(dev: boolean) {\n await construct_CertificateAuthority(\"\");\n await construct_CertificateManager();\n await create_default_certificates(dev);\n}\n\nimport commandLineArgs from \"command-line-args\";\nimport commandLineUsage from \"command-line-usage\";\n\nconst commonOptions = [\n {\n name: \"root\",\n alias: \"r\",\n type: String,\n defaultValue: \"{CWD}/certificates\",\n description: \"the location of the Certificate folder\"\n },\n {\n name: \"CAFolder\",\n alias: \"c\",\n type: String,\n defaultValue: \"{root}/CA\",\n description: \"the location of the Certificate Authority folder\"\n },\n { name: \"PKIFolder\", type: String, defaultValue: \"{root}/PKI\", description: \"the location of the Public Key Infrastructure\" },\n { name: \"silent\", type: Boolean, defaultValue: false, description: \"minimize output\" },\n {\n name: \"privateKey\",\n alias: \"p\",\n type: String,\n defaultValue: \"{PKIFolder}/own/private_key.pem\",\n description: \"the private key to use to generate certificate\"\n },\n {\n name: \"keySize\",\n alias: \"k\",\n type: Number,\n defaultValue: 2048,\n description: \"the private key size in bits (1024|2048|3072|4096)\"\n },\n { name: \"help\", alias: \"h\", type: Boolean, description: \"display this help\" }\n];\n\nfunction getOptions(names: string[]) {\n return commonOptions.filter((o) => names.includes(o.name) || o.name === \"help\" || o.name === \"silent\");\n}\n\nfunction showHelp(command: string, description: string, options: Record<string, unknown>[], usage?: string) {\n const sections = [\n {\n header: `Command: ${command}`,\n content: description\n },\n {\n header: \"Usage\",\n content: usage || `$0 ${command} [options]`\n },\n {\n header: \"Options\",\n optionList: options\n }\n ];\n console.log(commandLineUsage(sections));\n}\n\nexport async function main(argumentsList: string | string[]) {\n const mainDefinitions = [{ name: \"command\", defaultOption: true }];\n let mainOptions: commandLineArgs.CommandLineOptions;\n try {\n mainOptions = commandLineArgs(mainDefinitions, { argv: argumentsList as string[], stopAtFirstUnknown: true });\n } catch (err) {\n console.log((err as Error).message);\n return;\n }\n\n const argv = mainOptions._unknown || [];\n const command = mainOptions.command;\n\n if (!command || command === \"help\") {\n console.log(\n commandLineUsage([\n {\n header: \"node-opcua-pki\",\n content: `PKI management for node-opcua\\n\\n${epilog}`\n },\n {\n header: \"Commands\",\n content: [\n { name: \"demo\", summary: \"create default certificate for node-opcua demos\" },\n { name: \"createCA\", summary: \"create a Certificate Authority\" },\n { name: \"createPKI\", summary: \"create a Public Key Infrastructure\" },\n { name: \"certificate\", summary: \"create a new certificate\" },\n { name: \"revoke <certificateFile>\", summary: \"revoke a existing certificate\" },\n { name: \"csr\", summary: \"create a certificate signing request\" },\n { name: \"sign\", summary: \"validate a certificate signing request and generate a certificate\" },\n { name: \"dump <certificateFile>\", summary: \"display a certificate\" },\n { name: \"toder <pemCertificate>\", summary: \"convert a certificate to a DER format with finger print\" },\n { name: \"fingerprint <certificateFile>\", summary: \"print the certificate fingerprint\" },\n { name: \"version\", summary: \"display the version number\" }\n ]\n }\n ])\n );\n return;\n }\n\n if (command === \"version\") {\n const rootFolder = find_module_root_folder();\n const pkg = JSON.parse(fs.readFileSync(path.join(rootFolder, \"package.json\"), \"utf-8\"));\n console.log(pkg.version);\n return;\n }\n\n if (command === \"demo\") {\n const optionsDef = [\n ...getOptions([\"root\", \"silent\"]),\n { name: \"dev\", type: Boolean, description: \"create all sort of fancy certificates for dev testing purposes\" },\n { name: \"clean\", type: Boolean, description: \"Purge existing directory [use with care!]\" }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help)\n return showHelp(\n \"demo\",\n \"create default certificate for node-opcua demos\",\n optionsDef,\n \"$0 demo [--dev] [--silent] [--clean]\"\n );\n\n await wrap(async () => {\n await ensure_openssl_installed();\n displayChapter(\"Create Demo certificates\");\n displayTitle(\"reading configuration\");\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n if (local_argv.clean) {\n displayTitle(\"Cleaning old certificates\");\n assert(gLocalConfig);\n const certificateDir = gLocalConfig.certificateDir || \"\";\n const files = await fs.promises.readdir(certificateDir);\n for (const file of files) {\n if (file.includes(\".pem\") || file.includes(\".pub\")) {\n await fs.promises.unlink(path.join(certificateDir, file));\n }\n }\n mkdirRecursiveSync(certificateDir);\n }\n displayTitle(\"create certificates\");\n await createDefaultCertificates(local_argv.dev);\n displayChapter(\"Demo certificates CREATED\");\n });\n return;\n }\n\n if (command === \"createCA\") {\n const optionsDef = [\n ...getOptions([\"root\", \"CAFolder\", \"keySize\", \"silent\"]),\n { name: \"subject\", type: String, defaultValue: defaultSubject, description: \"the CA certificate subject\" }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help) return showHelp(\"createCA\", \"create a Certificate Authority\", optionsDef);\n\n await wrap(async () => {\n await ensure_openssl_installed();\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n await construct_CertificateAuthority(local_argv.subject);\n });\n return;\n }\n\n if (command === \"createPKI\") {\n const optionsDef = getOptions([\"root\", \"PKIFolder\", \"keySize\", \"silent\"]);\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help) return showHelp(\"createPKI\", \"create a Public Key Infrastructure\", optionsDef);\n\n await wrap(async () => {\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n await construct_CertificateManager();\n });\n return;\n }\n\n if (command === \"certificate\") {\n const optionsDef = [\n ...getOptions([\"root\", \"CAFolder\", \"PKIFolder\", \"privateKey\", \"silent\"]),\n {\n name: \"applicationUri\",\n alias: \"a\",\n type: String,\n defaultValue: \"urn:{hostname}:Node-OPCUA-Server\",\n description: \"the application URI\"\n },\n {\n name: \"output\",\n alias: \"o\",\n type: String,\n defaultValue: \"my_certificate.pem\",\n description: \"the name of the generated certificate =>\"\n },\n {\n name: \"selfSigned\",\n alias: \"s\",\n type: Boolean,\n defaultValue: false,\n description: \"if true, certificate will be self-signed\"\n },\n { name: \"validity\", alias: \"v\", type: Number, description: \"the certificate validity in days\" },\n {\n name: \"dns\",\n type: String,\n defaultValue: \"{hostname}\",\n description: \"the list of valid domain name (comma separated)\"\n },\n { name: \"ip\", type: String, defaultValue: \"\", description: \"the list of valid IPs (comma separated)\" },\n {\n name: \"subject\",\n type: String,\n defaultValue: \"\",\n description: \"the certificate subject ( for instance C=FR/ST=Centre/L=Orleans/O=SomeOrganization/CN=Hello )\"\n }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.applicationUri || !local_argv.output)\n return showHelp(\"certificate\", \"create a new certificate\", optionsDef);\n\n async function command_certificate(local_argv: IReadConfigurationOpts) {\n const selfSigned = !!(local_argv as unknown as { selfSigned?: boolean }).selfSigned;\n if (!selfSigned) {\n await command_full_certificate(local_argv);\n } else {\n await command_selfsigned_certificate(local_argv);\n }\n }\n\n async function command_selfsigned_certificate(local_argv: IReadConfigurationOpts) {\n const _fqdn = await extractFullyQualifiedDomainName();\n await readConfiguration(local_argv);\n await construct_CertificateManager();\n\n displaySubtitle(` create self signed Certificate ${gLocalConfig.outputFile}`);\n let subject =\n local_argv.subject && local_argv.subject.length > 1 ? new Subject(local_argv.subject) : gLocalConfig.subject || \"\";\n\n subject = JSON.parse(JSON.stringify(subject));\n\n const params: CreateSelfSignCertificateParam1 = {\n applicationUri: gLocalConfig.applicationUri || \"\",\n dns: gLocalConfig.dns || [],\n ip: gLocalConfig.ip || [],\n outputFile: gLocalConfig.outputFile || \"self_signed_certificate.pem\",\n startDate: gLocalConfig.startDate || new Date(),\n subject,\n validity: gLocalConfig.validity || 365\n };\n\n await certificateManager.createSelfSignedCertificate(params);\n }\n\n async function command_full_certificate(local_argv: IReadConfigurationOpts) {\n await readConfiguration(local_argv);\n await construct_CertificateManager();\n await construct_CertificateAuthority(\"\");\n assert(fs.existsSync(gLocalConfig.CAFolder || \"\"), \" CA folder must exist\");\n gLocalConfig.privateKey = undefined; // use PKI private key\n // create a Certificate Request from the certificate Manager\n\n gLocalConfig.subject = local_argv.subject && local_argv.subject.length > 1 ? local_argv.subject : gLocalConfig.subject;\n\n const csr_file = await certificateManager.createCertificateRequest(\n gLocalConfig as Parameters<typeof certificateManager.createCertificateRequest>[0]\n );\n if (!csr_file) {\n return;\n }\n warningLog(\" csr_file = \", csr_file);\n const certificate = csr_file.replace(\".csr\", \".pem\");\n\n if (fs.existsSync(certificate)) {\n throw new Error(` File ${certificate} already exist`);\n }\n await g_certificateAuthority.signCertificateRequest(\n certificate,\n csr_file,\n gLocalConfig as Parameters<typeof g_certificateAuthority.signCertificateRequest>[2]\n );\n\n assert(typeof gLocalConfig.outputFile === \"string\");\n fs.writeFileSync(gLocalConfig.outputFile || \"\", fs.readFileSync(certificate, \"ascii\"));\n }\n\n await wrap(async () => await command_certificate(local_argv as unknown as IReadConfigurationOpts));\n return;\n }\n\n if (command === \"revoke\") {\n const optionsDef = [{ name: \"certificateFile\", type: String, defaultOption: true }, ...getOptions([\"root\", \"CAFolder\"])];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.certificateFile)\n return showHelp(\n \"revoke <certificateFile>\",\n \"revoke a existing certificate\",\n optionsDef,\n \"$0 revoke my_certificate.pem\"\n );\n\n async function revoke_certificate(certificate: Filename) {\n await g_certificateAuthority.revokeCertificate(certificate, {});\n }\n\n await wrap(async () => {\n const certificate = path.resolve(local_argv.certificateFile);\n warningLog(chalk.yellow(\" Certificate to revoke : \"), chalk.cyan(certificate));\n if (!fs.existsSync(certificate)) {\n throw new Error(`cannot find certificate to revoke ${certificate}`);\n }\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n await construct_CertificateAuthority(\"\");\n await revoke_certificate(certificate);\n warningLog(\"done ... \");\n warningLog(\" crl = \", g_certificateAuthority.revocationList);\n warningLog(\"\\nyou should now publish the new Certificate Revocation List\");\n });\n return;\n }\n\n if (command === \"csr\") {\n const optionsDef = [\n ...getOptions([\"root\", \"PKIFolder\", \"privateKey\", \"silent\"]),\n {\n name: \"applicationUri\",\n alias: \"a\",\n type: String,\n defaultValue: \"urn:{hostname}:Node-OPCUA-Server\",\n description: \"the application URI\"\n },\n {\n name: \"output\",\n alias: \"o\",\n type: String,\n defaultValue: \"my_certificate_signing_request.csr\",\n description: \"the name of the generated signing_request\"\n },\n {\n name: \"dns\",\n type: String,\n defaultValue: \"{hostname}\",\n description: \"the list of valid domain name (comma separated)\"\n },\n { name: \"ip\", type: String, defaultValue: \"\", description: \"the list of valid IPs (comma separated)\" },\n {\n name: \"subject\",\n type: String,\n defaultValue: \"/CN=Certificate\",\n description: \"the certificate subject ( for instance /C=FR/ST=Centre/L=Orleans/O=SomeOrganization/CN=Hello )\"\n }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help) return showHelp(\"csr\", \"create a certificate signing request\", optionsDef);\n\n await wrap(async () => {\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n if (!fs.existsSync(gLocalConfig.PKIFolder || \"\")) {\n warningLog(\"PKI folder must exist\");\n }\n await construct_CertificateManager();\n if (!gLocalConfig.outputFile || fs.existsSync(gLocalConfig.outputFile)) {\n throw new Error(` File ${gLocalConfig.outputFile} already exist`);\n }\n gLocalConfig.privateKey = undefined; // use PKI private key\n // create a Certificate Request from the certificate Manager\n\n gLocalConfig.subject = local_argv.subject && local_argv.subject.length > 1 ? local_argv.subject : gLocalConfig.subject;\n\n const internal_csr_file = await certificateManager.createCertificateRequest(\n gLocalConfig as Parameters<typeof certificateManager.createCertificateRequest>[0]\n );\n if (!internal_csr_file) {\n return;\n }\n if (!gLocalConfig.outputFile) {\n warningLog(\"please specify a output file\");\n return;\n }\n const csr = await fs.promises.readFile(internal_csr_file, \"utf-8\");\n fs.writeFileSync(gLocalConfig.outputFile || \"\", csr, \"utf-8\");\n\n warningLog(\"Subject = \", gLocalConfig.subject);\n warningLog(\"applicationUri = \", gLocalConfig.applicationUri);\n warningLog(\"altNames = \", gLocalConfig.altNames);\n warningLog(\"dns = \", gLocalConfig.dns);\n warningLog(\"ip = \", gLocalConfig.ip);\n\n warningLog(\"CSR file = \", gLocalConfig.outputFile);\n });\n return;\n }\n\n if (command === \"sign\") {\n const optionsDef = [\n ...getOptions([\"root\", \"CAFolder\", \"silent\"]),\n { name: \"csr\", alias: \"i\", type: String, defaultValue: \"my_certificate_signing_request.csr\", description: \"the csr\" },\n {\n name: \"output\",\n alias: \"o\",\n type: String,\n defaultValue: \"my_certificate.pem\",\n description: \"the name of the generated certificate\"\n },\n { name: \"validity\", alias: \"v\", type: Number, defaultValue: 365, description: \"the certificate validity in days\" }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.csr || !local_argv.output)\n return showHelp(\"sign\", \"validate a certificate signing request and generate a certificate\", optionsDef);\n\n await wrap(async () => {\n await readConfiguration(local_argv as unknown as IReadConfigurationOpts);\n if (!fs.existsSync(gLocalConfig.CAFolder || \"\")) {\n throw new Error(`CA folder must exist:${gLocalConfig.CAFolder}`);\n }\n await construct_CertificateAuthority(\"\");\n const csr_file: string = path.resolve((local_argv as unknown as { csr?: string }).csr || \"\");\n if (!fs.existsSync(csr_file)) {\n throw new Error(`Certificate signing request doesn't exist: ${csr_file}`);\n }\n const certificate = path.resolve(local_argv.output || csr_file.replace(\".csr\", \".pem\"));\n if (fs.existsSync(certificate)) {\n throw new Error(` File ${certificate} already exist`);\n }\n\n await g_certificateAuthority.signCertificateRequest(\n certificate,\n csr_file,\n gLocalConfig as Parameters<typeof g_certificateAuthority.signCertificateRequest>[2]\n );\n\n assert(typeof gLocalConfig.outputFile === \"string\");\n fs.writeFileSync(gLocalConfig.outputFile || \"\", fs.readFileSync(certificate, \"ascii\"));\n });\n return;\n }\n\n if (command === \"dump\") {\n const optionsDef = [\n { name: \"certificateFile\", type: String, defaultOption: true },\n { name: \"help\", alias: \"h\", type: Boolean }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.certificateFile)\n return showHelp(\"dump <certificateFile>\", \"display a certificate\", optionsDef);\n\n await wrap(async () => {\n const data = await dumpCertificate(local_argv.certificateFile);\n warningLog(data);\n });\n return;\n }\n\n if (command === \"toder\") {\n const optionsDef = [\n { name: \"pemCertificate\", type: String, defaultOption: true },\n { name: \"help\", alias: \"h\", type: Boolean }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.pemCertificate)\n return showHelp(\"toder <pemCertificate>\", \"convert a certificate to a DER format with finger print\", optionsDef);\n\n await wrap(async () => {\n await toDer(local_argv.pemCertificate);\n });\n return;\n }\n\n if (command === \"fingerprint\") {\n const optionsDef = [\n { name: \"certificateFile\", type: String, defaultOption: true },\n { name: \"help\", alias: \"h\", type: Boolean }\n ];\n const local_argv = commandLineArgs(optionsDef, { argv });\n if (local_argv.help || !local_argv.certificateFile)\n return showHelp(\"fingerprint <certificateFile>\", \"print the certificate fingerprint\", optionsDef);\n\n await wrap(async () => {\n const certificate = local_argv.certificateFile;\n const data = await fingerprint(certificate);\n if (!data) return;\n const s = data.split(\"=\")[1].split(\":\").join(\"\").trim();\n warningLog(s);\n });\n return;\n }\n\n console.log(`Unknown command: ${command}`);\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\nimport { createHash } from \"node:crypto\";\n\nexport function makeApplicationUrn(hostname: string, suffix: string): string {\n // beware : Openssl doesn't support urn with length greater than 64 !!\n // sometimes hostname length could be too long ...\n // application urn length must not exceed 64 car. to comply with openssl\n // see cryptoCA\n let hostnameHash = hostname;\n if (hostnameHash.length + 7 + suffix.length >= 64) {\n // we need to reduce the applicationUrn side => let's take\n // a portion of the hostname hash.\n hostnameHash = createHash(\"md5\").update(hostname).digest(\"hex\").substring(0, 16);\n }\n\n const applicationUrn = `urn:${hostnameHash}:${suffix}`;\n assert(applicationUrn.length <= 64);\n return applicationUrn;\n}\n","/**\n * @module node-opcua-hostname\n */\nimport dns from \"node:dns\";\nimport os from \"node:os\";\nimport { promisify } from \"node:util\";\n\nfunction trim(str: string, length?: number): string {\n if (!length) {\n return str;\n }\n return str.substring(0, Math.min(str.length, length));\n}\n\nfunction fqdn(callback: (err: Error | null, fqdn?: string) => void) {\n const uqdn = os.hostname();\n\n dns.lookup(uqdn, { hints: dns.ADDRCONFIG }, (err1: Error | null, ip: string) => {\n if (err1) {\n return callback(err1);\n }\n\n dns.lookupService(ip, 0, (err2: Error | null, _fqdn: string) => {\n if (err2) {\n return callback(err2);\n }\n _fqdn = _fqdn.replace(\".localdomain\", \"\");\n callback(null, _fqdn);\n });\n });\n}\n\nlet _fullyQualifiedDomainNameInCache: string | undefined;\n\n/**\n * extract FullyQualifiedDomainName of this computer\n */\nexport async function extractFullyQualifiedDomainName(): Promise<string> {\n if (_fullyQualifiedDomainNameInCache) {\n return _fullyQualifiedDomainNameInCache;\n }\n if (process.platform === \"win32\") {\n // http://serverfault.com/a/73643/251863\n const env = process.env;\n _fullyQualifiedDomainNameInCache =\n env.COMPUTERNAME + (env.USERDNSDOMAIN && env.USERDNSDOMAIN?.length > 0 ? `.${env.USERDNSDOMAIN as string}` : \"\");\n } else {\n try {\n _fullyQualifiedDomainNameInCache = await promisify(fqdn)();\n if (_fullyQualifiedDomainNameInCache === \"localhost\") {\n throw new Error(\"localhost not expected\");\n }\n if (/sethostname/.test(_fullyQualifiedDomainNameInCache as string)) {\n throw new Error(\"Detecting fqdn on windows !!!\");\n }\n } catch (_err) {\n // fall back to old method\n _fullyQualifiedDomainNameInCache = os.hostname();\n }\n }\n return _fullyQualifiedDomainNameInCache as string;\n}\n\nexport async function prepareFQDN() {\n _fullyQualifiedDomainNameInCache = await extractFullyQualifiedDomainName();\n}\n\nexport function getFullyQualifiedDomainName(optional_max_length?: number) {\n if (!_fullyQualifiedDomainNameInCache) {\n throw new Error(\"FullyQualifiedDomainName computation is not completed yet\");\n }\n return _fullyQualifiedDomainNameInCache ? trim(_fullyQualifiedDomainNameInCache, optional_max_length) : \"%FQDN%\";\n}\n\nexport function getHostname() {\n return os.hostname();\n}\n\nexport function resolveFullyQualifiedDomainName(str: string): string {\n if (!_fullyQualifiedDomainNameInCache) {\n throw new Error(\"FullyQualifiedDomainName computation is not completed yet\");\n }\n str = str.replace(\"%FQDN%\", _fullyQualifiedDomainNameInCache);\n str = str.replace(\"{FQDN}\", _fullyQualifiedDomainNameInCache);\n str = str.replace(\"{hostname}\", getHostname());\n return str;\n}\n// note : under windows ... echo %COMPUTERNAME%.%USERDNSDOMAIN%\nprepareFQDN();\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki — CertificateManager\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2026 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n// This project is licensed under the terms of the MIT license.\n// ---------------------------------------------------------------------------------------------------------------------\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { withLock } from \"@ster5/global-mutex\";\nimport chalk from \"chalk\";\nimport chokidar from \"chokidar\";\nimport {\n type Certificate,\n type CertificateInternals,\n type CertificateRevocationList,\n type CertificateRevocationListInfo,\n type DER,\n exploreCertificate,\n exploreCertificateInfo,\n exploreCertificateRevocationList,\n generatePrivateKeyFile,\n makeSHA1Thumbprint,\n readCertificate,\n readCertificateRevocationList,\n split_der,\n toPem,\n verifyCertificateChain,\n verifyCertificateSignature\n} from \"node-opcua-crypto\";\n\nimport type { SubjectOptions } from \"../misc/subject\";\nimport type {\n CertificateStatus,\n CreateSelfSignCertificateParam,\n CreateSelfSignCertificateWithConfigParam,\n Filename,\n KeySize,\n Thumbprint\n} from \"../toolbox/common\";\nimport { makePath, mkdirRecursiveSync } from \"../toolbox/common2\";\nimport { debugLog, warningLog } from \"../toolbox/debug\";\nimport { createCertificateSigningRequestAsync, createSelfSignedCertificate } from \"../toolbox/without_openssl\";\n\nimport _simple_config_template from \"./templates/simple_config_template.cnf\";\n\n/**\n *\n * a minimalist config file for openssl that allows\n * self-signed certificate to be generated.\n *\n */\nconst configurationFileSimpleTemplate: string = _simple_config_template;\nconst fsWriteFile = fs.promises.writeFile;\n\ninterface Entry {\n certificate: Certificate;\n filename: string;\n /** Lazily cached result of `exploreCertificate(certificate)`. */\n info?: CertificateInternals;\n}\n\n/** Return the cached `info` or compute and cache it. */\nfunction getOrComputeInfo(entry: Entry): CertificateInternals {\n if (!entry.info) {\n entry.info = exploreCertificate(entry.certificate);\n }\n return entry.info;\n}\ninterface CRLEntry {\n crlInfo: CertificateRevocationListInfo;\n filename: string;\n}\ninterface CRLData {\n serialNumbers: { [key: string]: Date };\n crls: CRLEntry[];\n}\ninterface Thumbs {\n trusted: Map<string, Entry>;\n rejected: Map<string, Entry>;\n issuers: {\n certs: Map<string, Entry>;\n };\n /** key = subjectFingerPrint of issuer certificate */\n crl: Map<string, CRLData>;\n /** key = subjectFingerPrint of issuer certificate */\n issuersCrl: Map<string, CRLData>;\n}\n\nexport interface CertificateManagerOptions {\n keySize?: KeySize;\n location: string;\n}\n\nexport interface CreateSelfSignCertificateParam1 extends CreateSelfSignCertificateParam {\n outputFile?: Filename; // default : own/cert/self_signed_certificate.pem\n subject: SubjectOptions | string;\n applicationUri: string;\n dns: string[];\n startDate: Date;\n validity: number;\n}\n\nexport interface VerifyCertificateOptions {\n acceptOutdatedCertificate?: boolean;\n acceptOutDatedIssuerCertificate?: boolean;\n ignoreMissingRevocationList?: boolean;\n acceptPendingCertificate?: boolean;\n // rejectSelfSignedCertificate: boolean;\n}\n\nexport enum VerificationStatus {\n /** The certificate provided as a parameter is not valid. */\n BadCertificateInvalid = \"BadCertificateInvalid\",\n /** An error occurred verifying security. */\n BadSecurityChecksFailed = \"BadSecurityChecksFailed\",\n /** The certificate does not meet the requirements of the security policy. */\n BadCertificatePolicyCheckFailed = \"BadCertificatePolicyCheckFailed\",\n /** The certificate has expired or is not yet valid. */\n BadCertificateTimeInvalid = \"BadCertificateTimeInvalid\",\n /** An issuer certificate has expired or is not yet valid. */\n BadCertificateIssuerTimeInvalid = \"BadCertificateIssuerTimeInvalid\",\n /** The HostName used to connect to a server does not match a HostName in the certificate. */\n BadCertificateHostNameInvalid = \"BadCertificateHostNameInvalid\",\n /** The URI specified in the ApplicationDescription does not match the URI in the certificate. */\n BadCertificateUriInvalid = \"BadCertificateUriInvalid\",\n /** The certificate may not be used for the requested operation. */\n BadCertificateUseNotAllowed = \"BadCertificateUseNotAllowed\",\n /** The issuer certificate may not be used for the requested operation. */\n BadCertificateIssuerUseNotAllowed = \"BadCertificateIssuerUseNotAllowed\",\n /** The certificate is not trusted. */\n BadCertificateUntrusted = \"BadCertificateUntrusted\",\n /** It was not possible to determine if the certificate has been revoked. */\n BadCertificateRevocationUnknown = \"BadCertificateRevocationUnknown\",\n /** It was not possible to determine if the issuer certificate has been revoked. */\n BadCertificateIssuerRevocationUnknown = \"BadCertificateIssuerRevocationUnknown\",\n /** The certificate has been revoked. */\n BadCertificateRevoked = \"BadCertificateRevoked\",\n /** The issuer certificate has been revoked. */\n BadCertificateIssuerRevoked = \"BadCertificateIssuerRevoked\",\n /** The certificate chain is incomplete. */\n BadCertificateChainIncomplete = \"BadCertificateChainIncomplete\",\n\n /** Validation OK. */\n Good = \"Good\"\n}\n\nfunction makeFingerprint(certificate: Certificate | CertificateRevocationList): string {\n return makeSHA1Thumbprint(certificate).toString(\"hex\");\n}\nfunction short(stringToShorten: string) {\n return stringToShorten.substring(0, 10);\n}\n// biome-ignore lint/suspicious/noControlCharactersInRegex: we need to filter control characters\nconst forbiddenChars = /[\\x00-\\x1F<>:\"/\\\\|?*]/g;\nfunction buildIdealCertificateName(certificate: Certificate): string {\n const fingerprint = makeFingerprint(certificate);\n try {\n const commonName = exploreCertificate(certificate).tbsCertificate.subject.commonName || \"\";\n // commonName may contain invalid characters for a filename such as / or \\ or :\n // that we need to replace with a valid character.\n // replace / or \\ or : with _\n const sanitizedCommonName = commonName.replace(forbiddenChars, \"_\");\n return `${sanitizedCommonName}[${fingerprint}]`;\n } catch (_err) {\n // make be certificate is incorrect !\n return `invalid_certificate_[${fingerprint}]`;\n }\n}\nfunction findMatchingIssuerKey(entries: Entry[], wantedIssuerKey: string): Entry[] {\n return entries.filter((entry) => {\n const info = getOrComputeInfo(entry);\n return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;\n });\n}\n\nfunction isSelfSigned2(info: CertificateInternals): boolean {\n return (\n info.tbsCertificate.extensions?.subjectKeyIdentifier ===\n info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier\n );\n}\n\nfunction isSelfSigned3(certificate: Buffer): boolean {\n const info = exploreCertificate(certificate);\n return isSelfSigned2(info);\n}\n\nexport function findIssuerCertificateInChain(certificate: Certificate, chain: Certificate[]): Certificate | null {\n if (!certificate) {\n return null;\n }\n const certInfo = exploreCertificate(certificate);\n\n // istanbul ignore next\n if (isSelfSigned2(certInfo)) {\n // the certificate is self signed so is it's own issuer.\n return certificate;\n }\n const wantedIssuerKey = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;\n\n // istanbul ignore next\n if (!wantedIssuerKey) {\n // Certificate has no extension 3 ! the certificate might have been generated by an old system\n debugLog(\"Certificate has no extension 3\");\n return null;\n }\n const potentialIssuers = chain.filter((c) => {\n const info = exploreCertificate(c);\n return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;\n });\n\n if (potentialIssuers.length === 1) {\n return potentialIssuers[0];\n }\n if (potentialIssuers.length > 1) {\n debugLog(\"findIssuerCertificateInChain: certificate is not self-signed but has several issuers\");\n return potentialIssuers[0];\n }\n return null;\n}\n\nexport enum CertificateManagerState {\n Uninitialized = 0,\n Initializing = 1,\n Initialized = 2,\n Disposing = 3,\n Disposed = 4\n}\nexport class CertificateManager {\n public untrustUnknownCertificate = true;\n public state: CertificateManagerState = CertificateManagerState.Uninitialized;\n /** @deprecated Use {@link folderPollingInterval} instead (typo fix). */\n public folderPoolingInterval = 5000;\n\n /** Interval in milliseconds for file-system polling (when enabled). */\n public get folderPollingInterval(): number {\n return this.folderPoolingInterval;\n }\n public set folderPollingInterval(value: number) {\n this.folderPoolingInterval = value;\n }\n\n public readonly keySize: KeySize;\n private readonly location: string;\n private readonly _watchers: fs.FSWatcher[] = [];\n private _readCertificatesCalled = false;\n private readonly _filenameToHash = new Map<string, string>();\n private _initializingPromise?: Promise<void>;\n\n private readonly _thumbs: Thumbs = {\n rejected: new Map(),\n trusted: new Map(),\n issuers: {\n certs: new Map(),\n },\n crl: new Map(),\n issuersCrl: new Map(),\n };\n\n constructor(options: CertificateManagerOptions) {\n options.keySize = options.keySize || 2048;\n if (!options.location) {\n throw new Error(\"CertificateManager: missing 'location' option\");\n }\n\n this.location = makePath(options.location, \"\");\n this.keySize = options.keySize;\n\n mkdirRecursiveSync(options.location);\n\n if (!fs.existsSync(this.location)) {\n throw new Error(`CertificateManager cannot access location ${this.location}`);\n }\n }\n\n get configFile() {\n return path.join(this.rootDir, \"own/openssl.cnf\");\n }\n\n get rootDir() {\n return this.location;\n }\n\n get privateKey() {\n return path.join(this.rootDir, \"own/private/private_key.pem\");\n }\n\n get randomFile() {\n return path.join(this.rootDir, \"./random.rnd\");\n }\n\n /**\n * returns the certificate status trusted/rejected\n * @param certificate\n */\n public async getCertificateStatus(certificate: Buffer): Promise<CertificateStatus> {\n await this.initialize();\n let status = await this._checkRejectedOrTrusted(certificate);\n if (status === \"unknown\") {\n const pem = toPem(certificate, \"CERTIFICATE\");\n const fingerprint = makeFingerprint(certificate);\n const filename = path.join(this.rejectedFolder, `${buildIdealCertificateName(certificate)}.pem`);\n await fs.promises.writeFile(filename, pem);\n this._thumbs.rejected.set(fingerprint, { certificate, filename });\n status = \"rejected\";\n }\n return status;\n }\n\n /**\n * Move a certificate to the rejected store.\n * If the certificate was previously trusted, it will be moved.\n * @param certificate - the DER-encoded certificate\n */\n public async rejectCertificate(certificate: Certificate): Promise<void> {\n await this._moveCertificate(certificate, \"rejected\");\n }\n\n /**\n * Move a certificate to the trusted store.\n * If the certificate was previously rejected, it will be moved.\n * @param certificate - the DER-encoded certificate\n */\n public async trustCertificate(certificate: Certificate): Promise<void> {\n await this._moveCertificate(certificate, \"trusted\");\n }\n\n /** Path to the rejected certificates folder. */\n public get rejectedFolder(): string {\n return path.join(this.rootDir, \"rejected\");\n }\n /** Path to the trusted certificates folder. */\n public get trustedFolder(): string {\n return path.join(this.rootDir, \"trusted/certs\");\n }\n /** Path to the trusted CRL folder. */\n public get crlFolder(): string {\n return path.join(this.rootDir, \"trusted/crl\");\n }\n /** Path to the issuer (CA) certificates folder. */\n public get issuersCertFolder(): string {\n return path.join(this.rootDir, \"issuers/certs\");\n }\n /** Path to the issuer CRL folder. */\n public get issuersCrlFolder(): string {\n return path.join(this.rootDir, \"issuers/crl\");\n }\n\n /**\n * Check if a certificate is in the trusted store.\n * If the certificate is unknown and `untrustUnknownCertificate` is set,\n * it will be written to the rejected folder.\n * @param certificate - the DER-encoded certificate\n * @returns `\"Good\"` if trusted, `\"BadCertificateUntrusted\"` if rejected/unknown,\n * or `\"BadCertificateInvalid\"` if the certificate cannot be parsed.\n */\n public async isCertificateTrusted(certificate: Certificate): Promise<string> {\n const fingerprint = makeFingerprint(certificate) as Thumbprint;\n\n if (this._thumbs.trusted.has(fingerprint)) {\n return \"Good\";\n }\n\n if (!this._thumbs.rejected.has(fingerprint)) {\n if (!this.untrustUnknownCertificate) {\n return \"Good\";\n }\n // Verify structure before writing — don't persist invalid data\n try {\n exploreCertificateInfo(certificate);\n } catch (_err) {\n return \"BadCertificateInvalid\";\n }\n const filename = path.join(\n this.rejectedFolder,\n `${buildIdealCertificateName(certificate)}.pem`\n );\n debugLog(\"certificate has never been seen before and is now rejected (untrusted) \", filename);\n await fsWriteFile(filename, toPem(certificate, \"CERTIFICATE\"));\n this._thumbs.rejected.set(fingerprint, { certificate, filename });\n }\n return \"BadCertificateUntrusted\";\n }\n public async _innerVerifyCertificateAsync(\n certificate: Certificate,\n _isIssuer: boolean,\n level: number,\n options: VerifyCertificateOptions\n ): Promise<VerificationStatus> {\n if (level >= 5) {\n // maximum level of certificate in chain reached !\n return VerificationStatus.BadSecurityChecksFailed;\n }\n const chain = split_der(certificate);\n debugLog(\"NB CERTIFICATE IN CHAIN = \", chain.length);\n const info = exploreCertificate(chain[0]);\n\n let hasValidIssuer = false;\n let hasTrustedIssuer = false;\n // check if certificate is attached to a issuer\n const hasIssuerKey = info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;\n debugLog(\"Certificate as an Issuer Key\", hasIssuerKey);\n\n if (hasIssuerKey) {\n const isSelfSigned = isSelfSigned2(info);\n\n debugLog(\"Is the Certificate self-signed ?\", isSelfSigned);\n if (!isSelfSigned) {\n debugLog(\n \"Is issuer found in the list of know issuers ?\",\n \"\\n subjectKeyIdentifier = \",\n info.tbsCertificate.extensions?.subjectKeyIdentifier,\n \"\\n authorityKeyIdentifier = \",\n info.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier\n );\n let issuerCertificate = await this.findIssuerCertificate(chain[0]);\n if (!issuerCertificate) {\n // the issuer has not been found in the list of trusted certificate\n // may be the issuer certificate is in the chain itself ?\n issuerCertificate = findIssuerCertificateInChain(chain[0], chain);\n if (!issuerCertificate) {\n debugLog(\n \" the issuer has not been found in the chain itself nor in the issuer.cert list => the chain is incomplete!\"\n );\n return VerificationStatus.BadCertificateChainIncomplete;\n }\n debugLog(\" the issuer certificate has been found in the chain itself ! the chain is complete !\");\n } else {\n debugLog(\" the issuer certificate has been found in the issuer.cert folder !\");\n }\n const issuerStatus = await this._innerVerifyCertificateAsync(issuerCertificate, true, level + 1, options);\n if (issuerStatus === VerificationStatus.BadCertificateRevocationUnknown) {\n // the issuer must have a CRL available .... !\n return VerificationStatus.BadCertificateIssuerRevocationUnknown;\n }\n if (issuerStatus === VerificationStatus.BadCertificateIssuerRevocationUnknown) {\n // the issuer must have a CRL available .... !\n return VerificationStatus.BadCertificateIssuerRevocationUnknown;\n }\n if (issuerStatus === VerificationStatus.BadCertificateTimeInvalid) {\n if (!options || !options.acceptOutDatedIssuerCertificate) {\n // the issuer must have valid dates ....\n return VerificationStatus.BadCertificateIssuerTimeInvalid;\n }\n }\n if (issuerStatus === VerificationStatus.BadCertificateUntrusted) {\n debugLog(\"warning issuerStatus = \", issuerStatus.toString(), \"the issuer certificate is not trusted\");\n // return VerificationStatus.BadSecurityChecksFailed;\n }\n\n if (issuerStatus !== VerificationStatus.Good && issuerStatus !== VerificationStatus.BadCertificateUntrusted) {\n // if the issuer has other issue => let's drop!\n return VerificationStatus.BadSecurityChecksFailed;\n }\n // verify that certificate was signed by issuer\n const isCertificateSignatureOK = verifyCertificateSignature(certificate, issuerCertificate);\n if (!isCertificateSignatureOK) {\n debugLog(\" the certificate was not signed by the issuer as it claim to be ! Danger\");\n return VerificationStatus.BadSecurityChecksFailed;\n }\n hasValidIssuer = true;\n\n // let detected if our certificate is in the revocation list\n let revokedStatus = await this.isCertificateRevoked(certificate);\n if (revokedStatus === VerificationStatus.BadCertificateRevocationUnknown) {\n if (options?.ignoreMissingRevocationList) {\n // continue as if the certificate was not revoked\n revokedStatus = VerificationStatus.Good;\n }\n }\n if (revokedStatus !== VerificationStatus.Good) {\n // certificate is revoked !!!\n debugLog(\"revokedStatus\", revokedStatus);\n return revokedStatus;\n }\n\n // let check if the issuer is explicitly trusted\n const issuerTrustedStatus = await this._checkRejectedOrTrusted(issuerCertificate);\n debugLog(\"issuerTrustedStatus\", issuerTrustedStatus);\n\n if (issuerTrustedStatus === \"unknown\") {\n hasTrustedIssuer = false;\n } else if (issuerTrustedStatus === \"trusted\") {\n hasTrustedIssuer = true;\n } else if (issuerTrustedStatus === \"rejected\") {\n // we should never get there: this should have been detected before !!!\n return VerificationStatus.BadSecurityChecksFailed;\n }\n } else {\n // verify that certificate was signed by issuer (self in this case)\n const isCertificateSignatureOK = verifyCertificateSignature(certificate, certificate);\n if (!isCertificateSignatureOK) {\n debugLog(\"Self-signed Certificate signature is not valid\");\n return VerificationStatus.BadSecurityChecksFailed;\n }\n const revokedStatus = await this.isCertificateRevoked(certificate);\n debugLog(\"revokedStatus of self signed certificate:\", revokedStatus);\n }\n }\n\n const status = await this._checkRejectedOrTrusted(certificate);\n if (status === \"rejected\") {\n return VerificationStatus.BadCertificateUntrusted;\n }\n\n const _c2 = chain[1] ? exploreCertificateInfo(chain[1]) : \"non\";\n debugLog(\"chain[1] info=\", _c2);\n\n // Has SoftwareCertificate passed its issue date and has it not expired ?\n // check dates\n const certificateInfo = exploreCertificateInfo(certificate);\n const now = new Date();\n\n let isTimeInvalid = false;\n // check that certificate is active\n if (certificateInfo.notBefore.getTime() > now.getTime()) {\n // certificate is not active yet\n debugLog(\n chalk.red(\"certificate is invalid : certificate is not active yet !\") +\n \" not before date =\" +\n certificateInfo.notBefore\n );\n if (!options.acceptPendingCertificate) {\n isTimeInvalid = true;\n }\n }\n\n // check that certificate has not expired\n if (certificateInfo.notAfter.getTime() <= now.getTime()) {\n // certificate is obsolete\n debugLog(\n `${chalk.red(\"certificate is invalid : certificate has expired !\")} not after date =${certificateInfo.notAfter}`\n );\n if (!options.acceptOutdatedCertificate) {\n isTimeInvalid = true;\n }\n }\n if (status === \"trusted\") {\n return isTimeInvalid ? VerificationStatus.BadCertificateTimeInvalid : VerificationStatus.Good;\n }\n // status should be \"unknown\" at this point\n if (hasIssuerKey) {\n if (!hasTrustedIssuer) {\n return VerificationStatus.BadCertificateUntrusted;\n }\n if (!hasValidIssuer) {\n return VerificationStatus.BadCertificateUntrusted;\n }\n return isTimeInvalid ? VerificationStatus.BadCertificateTimeInvalid : VerificationStatus.Good;\n } else {\n return VerificationStatus.BadCertificateUntrusted;\n }\n }\n\n protected async verifyCertificateAsync(\n certificate: Certificate,\n options: VerifyCertificateOptions\n ): Promise<VerificationStatus> {\n const status1 = await this._innerVerifyCertificateAsync(certificate, false, 0, options);\n return status1;\n }\n\n /**\n * Verify certificate validity\n * @method verifyCertificate\n * @param certificate\n */\n public async verifyCertificate(certificate: Certificate, options?: VerifyCertificateOptions): Promise<VerificationStatus> {\n // Is the signature on the SoftwareCertificate valid .?\n if (!certificate) {\n // missing certificate\n return VerificationStatus.BadSecurityChecksFailed;\n }\n return await this.verifyCertificateAsync(certificate, options || {});\n }\n\n /*\n *\n * PKI\n * +---> trusted\n * +---> rejected\n * +---> own\n * +---> cert\n * +---> own\n *\n */\n public async initialize(): Promise<void> {\n if (this.state !== CertificateManagerState.Uninitialized) {\n return;\n }\n this.state = CertificateManagerState.Initializing;\n this._initializingPromise = this._initialize();\n await this._initializingPromise;\n this._initializingPromise = undefined;\n this.state = CertificateManagerState.Initialized;\n }\n private async _initialize(): Promise<void> {\n this.state = CertificateManagerState.Initializing;\n const pkiDir = this.location;\n mkdirRecursiveSync(pkiDir);\n mkdirRecursiveSync(path.join(pkiDir, \"own\"));\n mkdirRecursiveSync(path.join(pkiDir, \"own/certs\"));\n mkdirRecursiveSync(path.join(pkiDir, \"own/private\"));\n mkdirRecursiveSync(path.join(pkiDir, \"rejected\"));\n mkdirRecursiveSync(path.join(pkiDir, \"trusted\"));\n mkdirRecursiveSync(path.join(pkiDir, \"trusted/certs\"));\n mkdirRecursiveSync(path.join(pkiDir, \"trusted/crl\"));\n\n mkdirRecursiveSync(path.join(pkiDir, \"issuers\"));\n mkdirRecursiveSync(path.join(pkiDir, \"issuers/certs\")); // contains Trusted CA certificates\n mkdirRecursiveSync(path.join(pkiDir, \"issuers/crl\")); // contains CRL of revoked CA certificates\n\n if (!fs.existsSync(this.configFile) || !fs.existsSync(this.privateKey)) {\n return await this.withLock2(async () => {\n if (this.state === CertificateManagerState.Disposing || this.state === CertificateManagerState.Disposed) {\n return;\n }\n\n if (!fs.existsSync(this.configFile)) {\n fs.writeFileSync(this.configFile, configurationFileSimpleTemplate);\n }\n // note : openssl 1.1.1 has a bug that causes a failure if\n // random file cannot be found. (should be fixed in 1.1.1.a)\n // if this issue become important we may have to consider checking that rndFile exists and recreate\n // it if not . this could be achieved with the command :\n // \"openssl rand -writerand ${this.randomFile}\"\n //\n // cf: https://github.com/node-opcua/node-opcua/issues/554\n\n if (!fs.existsSync(this.privateKey)) {\n debugLog(\"generating private key ...\");\n // setEnv(\"RANDFILE\", this.randomFile);\n await generatePrivateKeyFile(this.privateKey, this.keySize);\n await this._readCertificates();\n } else {\n // debugLog(\" initialize : private key already exists ... skipping\");\n await this._readCertificates();\n }\n });\n } else {\n await this._readCertificates();\n }\n }\n\n /**\n * Dispose of the CertificateManager, releasing file watchers\n * and other resources. The instance should not be used after\n * calling this method.\n */\n public async dispose(): Promise<void> {\n if (this.state === CertificateManagerState.Disposing) {\n throw new Error(\"Already disposing\");\n }\n\n if (this.state === CertificateManagerState.Uninitialized) {\n this.state = CertificateManagerState.Disposed;\n return;\n }\n\n // Wait for initialization to complete before disposing\n if (this.state === CertificateManagerState.Initializing) {\n if (this._initializingPromise) {\n await this._initializingPromise;\n }\n }\n\n try {\n this.state = CertificateManagerState.Disposing;\n await Promise.all(this._watchers.map((w) => w.close()));\n this._watchers.forEach((w) => {\n w.removeAllListeners();\n });\n this._watchers.splice(0);\n } finally {\n this.state = CertificateManagerState.Disposed;\n }\n }\n\n /**\n * Force a full re-scan of all PKI folders, rebuilding\n * the in-memory `_thumbs` index from scratch.\n *\n * Call this after external processes have modified the\n * PKI folders (e.g. via `writeTrustList` or CLI tools)\n * to ensure the CertificateManager sees the latest\n * state without waiting for file-system events.\n */\n public async reloadCertificates(): Promise<void> {\n // Close existing watchers\n await Promise.all(this._watchers.map((w) => w.close()));\n for (const w of this._watchers) {\n w.removeAllListeners();\n }\n this._watchers.splice(0);\n\n // Clear in-memory indexes\n this._thumbs.rejected.clear();\n this._thumbs.trusted.clear();\n this._thumbs.issuers.certs.clear();\n this._thumbs.crl.clear();\n this._thumbs.issuersCrl.clear();\n this._filenameToHash.clear();\n\n // Re-scan all folders\n this._readCertificatesCalled = false;\n await this._readCertificates();\n }\n\n protected async withLock2<T>(action: () => Promise<T>): Promise<T> {\n const lockFileName = path.join(this.rootDir, \"mutex.lock\");\n return withLock<T>({ fileToLock: lockFileName }, async () => {\n return await action();\n });\n }\n /**\n *\n * create a self-signed certificate for the CertificateManager private key\n *\n */\n public async createSelfSignedCertificate(params: CreateSelfSignCertificateParam1): Promise<void> {\n if (typeof params.applicationUri !== \"string\") {\n throw new Error(\"createSelfSignedCertificate: expecting applicationUri to be a string\");\n }\n if (!fs.existsSync(this.privateKey)) {\n throw new Error(`Cannot find private key ${this.privateKey}`);\n }\n let certificateFilename = path.join(this.rootDir, \"own/certs/self_signed_certificate.pem\");\n certificateFilename = params.outputFile || certificateFilename;\n\n const _params = params as unknown as CreateSelfSignCertificateWithConfigParam;\n _params.rootDir = this.rootDir;\n _params.configFile = this.configFile;\n _params.privateKey = this.privateKey;\n\n _params.subject = params.subject || \"CN=FIXME\";\n await this.withLock2(async () => {\n await createSelfSignedCertificate(certificateFilename, _params);\n });\n }\n\n public async createCertificateRequest(params: CreateSelfSignCertificateParam): Promise<Filename> {\n if (!params) {\n throw new Error(\"params is required\");\n }\n const _params = params as CreateSelfSignCertificateWithConfigParam;\n if (Object.prototype.hasOwnProperty.call(_params, \"rootDir\")) {\n throw new Error(\"rootDir should not be specified \");\n }\n _params.rootDir = path.resolve(this.rootDir);\n _params.configFile = path.resolve(this.configFile);\n _params.privateKey = path.resolve(this.privateKey);\n\n return await this.withLock2<string>(async () => {\n // compose a file name for the request\n const now = new Date();\n const today = `${now.toISOString().slice(0, 10)}_${now.getTime()}`;\n const certificateSigningRequestFilename = path.join(this.rootDir, \"own/certs\", `certificate_${today}.csr`);\n await createCertificateSigningRequestAsync(certificateSigningRequestFilename, _params);\n return certificateSigningRequestFilename;\n });\n }\n\n /**\n * Add a CA (issuer) certificate to the issuers store.\n * If the certificate is already present, this is a no-op.\n * @param certificate - the DER-encoded CA certificate\n * @param validate - if `true`, verify the certificate before adding\n * @param addInTrustList - if `true`, also add to the trusted store\n * @returns `VerificationStatus.Good` on success\n */\n public async addIssuer(certificate: DER, validate = false, addInTrustList = false): Promise<VerificationStatus> {\n if (validate) {\n const status = await this.verifyCertificate(certificate);\n if (status !== VerificationStatus.Good && status !== VerificationStatus.BadCertificateUntrusted) {\n return status;\n }\n }\n const pemCertificate = toPem(certificate, \"CERTIFICATE\");\n const fingerprint = makeFingerprint(certificate);\n if (this._thumbs.issuers.certs.has(fingerprint)) {\n // already in .. simply ignore\n return VerificationStatus.Good;\n }\n // write certificate\n const filename = path.join(this.issuersCertFolder, `issuer_${buildIdealCertificateName(certificate)}.pem`);\n await fs.promises.writeFile(filename, pemCertificate, \"ascii\");\n\n // first time seen, let's save it.\n this._thumbs.issuers.certs.set(fingerprint, { certificate, filename });\n\n if (addInTrustList) {\n // add certificate in the trust list as well\n await this.trustCertificate(certificate);\n }\n\n return VerificationStatus.Good;\n }\n\n /**\n * Add a CRL to the certificate manager.\n * @param crl - the CRL to add\n * @param target - \"issuers\" (default) writes to issuers/crl, \"trusted\" writes to trusted/crl\n */\n public async addRevocationList(\n crl: CertificateRevocationList,\n target: \"issuers\" | \"trusted\" = \"issuers\"\n ): Promise<VerificationStatus> {\n return await this.withLock2<VerificationStatus>(async () => {\n try {\n const index = target === \"trusted\" ? this._thumbs.crl : this._thumbs.issuersCrl;\n const folder = target === \"trusted\" ? this.crlFolder : this.issuersCrlFolder;\n\n const crlInfo = exploreCertificateRevocationList(crl);\n const key = crlInfo.tbsCertList.issuerFingerprint;\n if (!index.has(key)) {\n index.set(key, { crls: [], serialNumbers: {} });\n }\n const pemCertificate = toPem(crl, \"X509 CRL\");\n const filename = path.join(folder, `crl_${buildIdealCertificateName(crl)}.pem`);\n await fs.promises.writeFile(filename, pemCertificate, \"ascii\");\n\n await this._on_crl_file_added(index, filename);\n\n await this.waitAndCheckCRLProcessingStatus();\n\n return VerificationStatus.Good;\n } catch (err) {\n debugLog(err);\n return VerificationStatus.BadSecurityChecksFailed;\n }\n });\n }\n\n /**\n * Remove all CRL files from the specified folder(s) and clear the\n * corresponding in-memory index.\n * @param target - \"issuers\" clears issuers/crl, \"trusted\" clears\n * trusted/crl, \"all\" clears both.\n */\n public async clearRevocationLists(target: \"issuers\" | \"trusted\" | \"all\"): Promise<void> {\n const clearFolder = async (folder: string, index: Map<string, CRLData>) => {\n try {\n const files = await fs.promises.readdir(folder);\n for (const file of files) {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".crl\" || ext === \".pem\" || ext === \".der\") {\n await fs.promises.unlink(path.join(folder, file));\n }\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n index.clear();\n };\n\n if (target === \"issuers\" || target === \"all\") {\n await clearFolder(this.issuersCrlFolder, this._thumbs.issuersCrl);\n }\n if (target === \"trusted\" || target === \"all\") {\n await clearFolder(this.crlFolder, this._thumbs.crl);\n }\n }\n\n /**\n * Check whether an issuer certificate with the given thumbprint\n * is already registered.\n * @param thumbprint - hex-encoded SHA-1 thumbprint (lowercase)\n */\n public async hasIssuer(thumbprint: string): Promise<boolean> {\n await this._readCertificates();\n const normalized = thumbprint.toLowerCase();\n return this._thumbs.issuers.certs.has(normalized);\n }\n\n /**\n * Remove a trusted certificate identified by its SHA-1 thumbprint.\n * Deletes the file on disk and removes the entry from the\n * in-memory index.\n * @param thumbprint - hex-encoded SHA-1 thumbprint (lowercase)\n * @returns the removed certificate buffer, or `null` if not found\n */\n public async removeTrustedCertificate(thumbprint: string): Promise<Certificate | null> {\n await this._readCertificates();\n const normalized = thumbprint.toLowerCase();\n const entry = this._thumbs.trusted.get(normalized);\n if (!entry) {\n return null;\n }\n try {\n await fs.promises.unlink(entry.filename);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n this._thumbs.trusted.delete(normalized);\n return entry.certificate;\n }\n\n /**\n * Remove an issuer certificate identified by its SHA-1 thumbprint.\n * Deletes the file on disk and removes the entry from the\n * in-memory index.\n * @param thumbprint - hex-encoded SHA-1 thumbprint (lowercase)\n * @returns the removed certificate buffer, or `null` if not found\n */\n public async removeIssuer(thumbprint: string): Promise<Certificate | null> {\n await this._readCertificates();\n const normalized = thumbprint.toLowerCase();\n const entry = this._thumbs.issuers.certs.get(normalized);\n if (!entry) {\n return null;\n }\n try {\n await fs.promises.unlink(entry.filename);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n this._thumbs.issuers.certs.delete(normalized);\n return entry.certificate;\n }\n\n /**\n * Remove all CRL files that were issued by the given CA certificate\n * from the specified folder (or both).\n * @param issuerCertificate - the CA certificate whose CRLs to remove\n * @param target - \"issuers\", \"trusted\", or \"all\" (default \"all\")\n */\n public async removeRevocationListsForIssuer(\n issuerCertificate: Certificate,\n target: \"issuers\" | \"trusted\" | \"all\" = \"all\"\n ): Promise<void> {\n const issuerInfo = exploreCertificate(issuerCertificate);\n const issuerFingerprint = issuerInfo.tbsCertificate.subjectFingerPrint;\n\n const processIndex = async (index: Map<string, CRLData>) => {\n const crlData = index.get(issuerFingerprint);\n if (!crlData) return;\n for (const crlEntry of crlData.crls) {\n try {\n await fs.promises.unlink(crlEntry.filename);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n }\n index.delete(issuerFingerprint);\n };\n\n if (target === \"issuers\" || target === \"all\") {\n await processIndex(this._thumbs.issuersCrl);\n }\n if (target === \"trusted\" || target === \"all\") {\n await processIndex(this._thumbs.crl);\n }\n }\n\n /**\n * Validate a certificate (optionally with its chain) and add\n * the leaf certificate to the trusted store.\n *\n * The certificate buffer may contain a single certificate or a\n * full chain (leaf + issuer certificates concatenated in DER).\n * Only the leaf certificate is added to the trusted store.\n *\n * When the chain contains issuer certificates, this method\n * verifies that each issuer is already registered via\n * {@link addIssuer} before trusting the leaf.\n *\n * @param certificateChain - DER-encoded certificate or chain\n * @returns `VerificationStatus.Good` on success, or an error\n * status indicating why the certificate was rejected.\n */\n public async addTrustedCertificateFromChain(certificateChain: Certificate): Promise<VerificationStatus> {\n const certificates = split_der(certificateChain);\n const leafCertificate = certificates[0];\n\n // Structural validation — can we parse it?\n try {\n exploreCertificate(leafCertificate);\n } catch (_err) {\n return VerificationStatus.BadCertificateInvalid;\n }\n\n // Lightweight chain validation — verify the certificate\n // structure and signature without trust-store side-effects\n const result = await verifyCertificateChain([leafCertificate]);\n if (result.status !== \"Good\") {\n return VerificationStatus.BadCertificateInvalid;\n }\n\n // If a chain was provided, verify that every issuer in the\n // chain is already registered in the issuers store.\n // We scan the filesystem directly because issuers may have\n // been added outside this CertificateManager instance (e.g.\n // via writeTrustedCertificateList) and the in-memory index\n // may be stale.\n if (certificates.length > 1) {\n const issuerFolder = this.issuersCertFolder;\n const issuerThumbprints = new Set<string>();\n const files = await fs.promises.readdir(issuerFolder);\n for (const file of files) {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".pem\" || ext === \".der\") {\n try {\n const issuerCert = readCertificate(path.join(issuerFolder, file));\n const fp = makeFingerprint(issuerCert);\n issuerThumbprints.add(fp);\n } catch (_err) {\n // skip unreadable files\n }\n }\n }\n for (const issuerCert of certificates.slice(1)) {\n const thumbprint = makeFingerprint(issuerCert);\n if (!issuerThumbprints.has(thumbprint)) {\n return VerificationStatus.BadCertificateChainIncomplete;\n }\n }\n }\n\n // All checks passed — trust the leaf certificate\n await this.trustCertificate(leafCertificate);\n return VerificationStatus.Good;\n }\n\n /**\n * Check whether an issuer certificate is still needed by any\n * certificate in the trusted store.\n *\n * This is used before removing an issuer to ensure that\n * doing so would not break the chain of any trusted\n * certificate.\n *\n * @param issuerCertificate - the CA certificate to check\n * @returns `true` if at least one trusted certificate was\n * signed by this issuer.\n */\n public async isIssuerInUseByTrustedCertificate(issuerCertificate: Certificate): Promise<boolean> {\n await this._readCertificates();\n for (const entry of this._thumbs.trusted.values()) {\n if (!entry.certificate) continue;\n try {\n if (verifyCertificateSignature(entry.certificate, issuerCertificate)) {\n return true;\n }\n } catch (_err) {\n // Skip certificates that can't be verified\n }\n }\n return false;\n }\n\n /**\n * find the issuer certificate among the trusted issuer certificates.\n *\n * The findIssuerCertificate method is an asynchronous method that attempts to find\n * the issuer certificate for a given certificate from the list of issuer certificate declared in the PKI\n *\n * - If the certificate is self-signed, it returns the certificate itself.\n *\n * - If the certificate has no extension 3, it is assumed to be generated by an old system, and a null value is returned.\n *\n * - the method checks both issuer and trusted certificates and returns the appropriate issuercertificate,\n * if found. If multiple matching certificates are found, a warning is logged to the console.\n *\n */\n public async findIssuerCertificate(certificate: Certificate): Promise<Certificate | null> {\n const certInfo = exploreCertificate(certificate);\n\n if (isSelfSigned2(certInfo)) {\n // the certificate is self signed so is it's own issuer.\n return certificate;\n }\n\n const wantedIssuerKey = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier;\n\n if (!wantedIssuerKey) {\n // Certificate has no extension 3 ! the certificate might have been generated by an old system\n debugLog(\"Certificate has no extension 3\");\n return null;\n }\n\n const issuerCertificates = [...this._thumbs.issuers.certs.values()];\n\n const selectedIssuerCertificates = findMatchingIssuerKey(issuerCertificates, wantedIssuerKey);\n\n if (selectedIssuerCertificates.length > 0) {\n if (selectedIssuerCertificates.length > 1) {\n warningLog(\"Warning more than one issuer certificate exists with subjectKeyIdentifier \", wantedIssuerKey);\n }\n return selectedIssuerCertificates[0].certificate || null;\n }\n // check also in trusted list\n const trustedCertificates = [...this._thumbs.trusted.values()];\n const selectedTrustedCertificates = findMatchingIssuerKey(trustedCertificates, wantedIssuerKey);\n\n if (selectedTrustedCertificates.length > 1) {\n warningLog(\n \"Warning more than one certificate exists with subjectKeyIdentifier in trusted certificate list \",\n wantedIssuerKey,\n selectedTrustedCertificates.length\n );\n }\n return selectedTrustedCertificates.length > 0 ? selectedTrustedCertificates[0].certificate : null;\n }\n\n /**\n * @internal\n * @private\n */\n public async _checkRejectedOrTrusted(certificate: Buffer): Promise<CertificateStatus> {\n const fingerprint = makeFingerprint(certificate);\n\n debugLog(\"_checkRejectedOrTrusted fingerprint \", short(fingerprint));\n\n await this._readCertificates();\n\n if (this._thumbs.rejected.has(fingerprint)) {\n return \"rejected\";\n }\n if (this._thumbs.trusted.has(fingerprint)) {\n return \"trusted\";\n }\n return \"unknown\";\n }\n\n private async _moveCertificate(certificate: Certificate, newStatus: CertificateStatus) {\n await this.withLock2(async () => {\n const fingerprint = makeFingerprint(certificate);\n\n const status = await this.getCertificateStatus(certificate);\n debugLog(\"_moveCertificate\", fingerprint.substring(0, 10), \"from\", status, \"to\", newStatus);\n if (status !== \"rejected\" && status !== \"trusted\") {\n throw new Error(`_moveCertificate: unexpected status '${status}' for certificate ${fingerprint.substring(0, 10)}`);\n }\n\n if (status !== newStatus) {\n const indexSrc = status === \"rejected\" ? this._thumbs.rejected : this._thumbs.trusted;\n const srcEntry = indexSrc.get(fingerprint);\n\n if (!srcEntry) {\n debugLog(\" cannot find certificate \", fingerprint.substring(0, 10), \" in\", status);\n throw new Error(`_moveCertificate: certificate ${fingerprint.substring(0, 10)} not found in ${status} index`);\n }\n const destFolder = newStatus === \"trusted\" ? this.trustedFolder : this.rejectedFolder;\n const certificateDest = path.join(destFolder, path.basename(srcEntry.filename));\n\n debugLog(\"_moveCertificate\", fingerprint.substring(0, 10), \"old name\", srcEntry.filename);\n debugLog(\"_moveCertificate\", fingerprint.substring(0, 10), \"new name\", certificateDest);\n await fs.promises.rename(srcEntry.filename, certificateDest);\n indexSrc.delete(fingerprint);\n const indexDest = newStatus === \"trusted\" ? this._thumbs.trusted : this._thumbs.rejected;\n indexDest.set(fingerprint, { certificate, filename: certificateDest });\n }\n });\n }\n private _findAssociatedCRLs(issuerCertificate: Certificate): CRLData | null {\n const issuerCertificateInfo = exploreCertificate(issuerCertificate);\n const key = issuerCertificateInfo.tbsCertificate.subjectFingerPrint;\n return this._thumbs.issuersCrl.get(key) ?? this._thumbs.crl.get(key) ?? null;\n }\n\n public async isCertificateRevoked(\n certificate: Certificate,\n issuerCertificate?: Certificate | null\n ): Promise<VerificationStatus> {\n if (isSelfSigned3(certificate)) {\n return VerificationStatus.Good;\n }\n\n if (!issuerCertificate) {\n issuerCertificate = await this.findIssuerCertificate(certificate);\n }\n if (!issuerCertificate) {\n return VerificationStatus.BadCertificateChainIncomplete;\n }\n const crls = this._findAssociatedCRLs(issuerCertificate);\n\n if (!crls) {\n return VerificationStatus.BadCertificateRevocationUnknown;\n }\n const certInfo = exploreCertificate(certificate);\n const serialNumber =\n certInfo.tbsCertificate.serialNumber || certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.serial || \"\";\n\n const key = certInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.authorityCertIssuerFingerPrint || \"<unknown>\";\n const crl2 = this._thumbs.crl.get(key) ?? null;\n\n if (crls.serialNumbers[serialNumber] || crl2?.serialNumbers[serialNumber]) {\n return VerificationStatus.BadCertificateRevoked;\n }\n return VerificationStatus.Good;\n }\n\n private _pending_crl_to_process = 0;\n private _on_crl_process?: () => void;\n private queue: { index: Map<string, CRLData>; filename: string }[] = [];\n private _on_crl_file_added(index: Map<string, CRLData>, filename: string) {\n this.queue.push({ index, filename });\n this._pending_crl_to_process += 1;\n if (this._pending_crl_to_process === 1) {\n this._process_next_crl();\n }\n }\n private async _process_next_crl() {\n try {\n const nextCRL = this.queue.shift();\n if (!nextCRL) return;\n const { index, filename } = nextCRL;\n const crl = await readCertificateRevocationList(filename);\n const crlInfo = exploreCertificateRevocationList(crl);\n debugLog(chalk.cyan(\"add CRL in folder \"), filename);\n const fingerprint = crlInfo.tbsCertList.issuerFingerprint;\n if (!index.has(fingerprint)) {\n index.set(fingerprint, { crls: [], serialNumbers: {} });\n }\n const data = index.get(fingerprint) || { crls: [], serialNumbers: {} };\n data.crls.push({ crlInfo, filename });\n\n // now inject serial numbers\n for (const revokedCertificate of crlInfo.tbsCertList.revokedCertificates) {\n const serialNumber = revokedCertificate.userCertificate;\n if (!data.serialNumbers[serialNumber]) {\n data.serialNumbers[serialNumber] = revokedCertificate.revocationDate;\n }\n }\n debugLog(chalk.cyan(\"CRL\"), fingerprint, \"serial numbers = \", Object.keys(data.serialNumbers));\n } catch (err) {\n debugLog(\"CRL filename error =\");\n debugLog(err);\n }\n this._pending_crl_to_process -= 1;\n if (this._pending_crl_to_process === 0) {\n if (this._on_crl_process) {\n this._on_crl_process();\n this._on_crl_process = undefined;\n }\n } else {\n this._process_next_crl();\n }\n }\n private async _readCertificates(): Promise<void> {\n if (this._readCertificatesCalled) {\n return;\n }\n this._readCertificatesCalled = true;\n\n // Chokidar configuration choices:\n //\n // usePolling: false (default)\n // Use native OS file-system events (inotify on Linux,\n // FSEvents on macOS, ReadDirectoryChangesW on Windows)\n // for near-real-time detection of cert/CRL additions\n // and removals. This is significantly faster than\n // polling (milliseconds vs seconds).\n //\n // Set OPCUA_PKI_USE_POLLING=true to revert to polling\n // for environments where native events are unreliable\n // (NFS, CIFS, Docker volumes, or other remote/virtual\n // file systems).\n //\n // persistent: false\n // Watchers do NOT keep the Node.js event loop alive.\n // This prevents the process from hanging if the\n // CertificateManager is not properly disposed. The\n // trade-off is that watchers stop receiving events if\n // there are no other active handles — acceptable since\n // CertificateManager always runs alongside a server.\n //\n // awaitWriteFinish: not set\n // Certificate and CRL files are small (typically < 5 KB)\n // and written atomically (fs.writeFile). No need to\n // wait for write stabilization, which would add a 2s+\n // delay before the in-memory index is updated.\n //\n const usePolling = process.env.OPCUA_PKI_USE_POLLING === \"true\";\n const options = {\n usePolling,\n ...(usePolling ? { interval: Math.min(10 * 60 * 1000, Math.max(100, this.folderPoolingInterval)) } : {}),\n persistent: false\n };\n async function _walkCRLFiles(this: CertificateManager, folder: string, index: Map<string, CRLData>) {\n await new Promise<void>((resolve, _reject) => {\n const w = chokidar.watch(folder, options);\n\n w.on(\"unlink\", (filename: string) => {\n // Remove CRL entries whose file was deleted\n for (const [key, data] of index.entries()) {\n data.crls = data.crls.filter((c) => c.filename !== filename);\n if (data.crls.length === 0) {\n index.delete(key);\n }\n }\n });\n w.on(\"add\", (filename: string) => {\n this._on_crl_file_added(index, filename);\n });\n w.on(\"change\", (changedPath: string) => {\n debugLog(\"change in folder \", folder, changedPath);\n });\n this._watchers.push(w as unknown as fs.FSWatcher);\n w.on(\"ready\", () => {\n resolve();\n });\n });\n }\n\n async function _walkAllFiles(this: CertificateManager, folder: string, index: Map<string, Entry>) {\n const w = chokidar.watch(folder, options);\n w.on(\"unlink\", (filename: string) => {\n debugLog(chalk.cyan(`unlink in folder ${folder}`), filename);\n const h = this._filenameToHash.get(filename);\n if (h && index.has(h)) {\n index.delete(h);\n }\n });\n w.on(\"add\", (filename: string) => {\n debugLog(chalk.cyan(`add in folder ${folder}`), filename);\n try {\n const certificate = readCertificate(filename);\n const info = exploreCertificate(certificate);\n const fingerprint = makeFingerprint(certificate);\n\n index.set(fingerprint, { certificate, filename, info });\n this._filenameToHash.set(filename, fingerprint);\n\n debugLog(\n chalk.magenta(\"CERT\"),\n info.tbsCertificate.subjectFingerPrint,\n info.tbsCertificate.serialNumber,\n info.tbsCertificate.extensions?.authorityKeyIdentifier?.authorityCertIssuerFingerPrint\n );\n } catch (err) {\n debugLog(`Walk files in folder ${folder} with file ${filename}`);\n debugLog(err);\n }\n });\n w.on(\"change\", (changedPath: string) => {\n debugLog(chalk.cyan(`change in folder ${folder}`), changedPath);\n try {\n const certificate = readCertificate(changedPath);\n const newFingerprint = makeFingerprint(certificate);\n // Remove old entry if fingerprint changed\n const oldHash = this._filenameToHash.get(changedPath);\n if (oldHash && oldHash !== newFingerprint) {\n index.delete(oldHash);\n }\n index.set(newFingerprint, { certificate, filename: changedPath, info: exploreCertificate(certificate) });\n this._filenameToHash.set(changedPath, newFingerprint);\n } catch (err) {\n debugLog(`change event: failed to re-read ${changedPath}`, err);\n }\n });\n this._watchers.push(w as unknown as fs.FSWatcher);\n await new Promise<void>((resolve, _reject) => {\n w.on(\"ready\", () => {\n debugLog(\"ready\");\n debugLog([...index.keys()].map((k) => k.substring(0, 10)));\n resolve();\n });\n });\n }\n\n const promises: Promise<void>[] = [\n _walkAllFiles.bind(this, this.trustedFolder, this._thumbs.trusted)(),\n _walkAllFiles.bind(this, this.issuersCertFolder, this._thumbs.issuers.certs)(),\n _walkAllFiles.bind(this, this.rejectedFolder, this._thumbs.rejected)(),\n _walkCRLFiles.bind(this, this.crlFolder, this._thumbs.crl)(),\n _walkCRLFiles.bind(this, this.issuersCrlFolder, this._thumbs.issuersCrl)()\n ];\n await Promise.all(promises);\n await this.waitAndCheckCRLProcessingStatus();\n }\n\n // make sure that all crls have been processed.\n private async waitAndCheckCRLProcessingStatus(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this._pending_crl_to_process === 0) {\n setImmediate(resolve);\n return;\n }\n if (this._on_crl_process) {\n return reject(new Error(\"Internal Error\"));\n }\n this._on_crl_process = resolve;\n });\n }\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2022-2026 Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport { createCertificateSigningRequest, pemToPrivateKey, Subject } from \"node-opcua-crypto\";\nimport type { CreateCertificateSigningRequestWithConfigOptions } from \"../common\";\nimport { display, displaySubtitle } from \"../display\";\n\n/**\n * create a certificate signing request\n */\nexport async function createCertificateSigningRequestAsync(\n certificateSigningRequestFilename: string,\n params: CreateCertificateSigningRequestWithConfigOptions\n): Promise<void> {\n assert(params);\n assert(params.rootDir);\n assert(params.configFile);\n assert(params.privateKey);\n assert(typeof params.privateKey === \"string\");\n assert(fs.existsSync(params.privateKey), `Private key must exist${params.privateKey}`);\n\n // assert(fs.existsSync(params.configFile), \"config file must exist \" + params.configFile);\n assert(fs.existsSync(params.rootDir), \"RootDir key must exist\");\n assert(typeof certificateSigningRequestFilename === \"string\");\n\n const subject = params.subject ? new Subject(params.subject).toString() : undefined;\n displaySubtitle(\"- Creating a Certificate Signing Request with subtile\");\n\n const privateKeyPem = await fs.promises.readFile(params.privateKey, \"utf-8\");\n const privateKey = await pemToPrivateKey(privateKeyPem);\n\n const { csr } = await createCertificateSigningRequest({\n privateKey,\n dns: params.dns,\n ip: params.ip,\n subject,\n applicationUri: params.applicationUri,\n purpose: params.purpose\n });\n await fs.promises.writeFile(certificateSigningRequestFilename, csr, \"utf-8\");\n\n display(`- privateKey ${params.privateKey}`);\n display(`- certificateSigningRequestFilename ${certificateSigningRequestFilename}`);\n\n // to verify that the CSR is correct:\n // openssl req -in ./tmp/without_openssl.csr -noout -verify\n}\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-pki\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2022-2026 Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\nimport assert from \"node:assert\";\nimport fs from \"node:fs\";\n\nimport {\n CertificatePurpose,\n createSelfSignedCertificate as createSelfSignedCertificate1,\n pemToPrivateKey,\n Subject\n} from \"node-opcua-crypto\";\nimport { adjustDate, type CreateSelfSignCertificateWithConfigParam } from \"../common\";\nimport { displayTitle } from \"../display\";\n\nexport async function createSelfSignedCertificateAsync(\n certificate: string,\n params: CreateSelfSignCertificateWithConfigParam\n): Promise<void> {\n params.purpose = params.purpose || CertificatePurpose.ForApplication;\n assert(params.purpose, \"Please provide a Certificate Purpose\");\n /**\n * note: due to a limitation of openssl ,\n * it is not possible to control the startDate of the certificate validity\n * to achieve this the certificateAuthority tool shall be used.\n */\n assert(fs.existsSync(params.configFile));\n assert(fs.existsSync(params.rootDir));\n assert(fs.existsSync(params.privateKey));\n if (!params.subject) {\n throw Error(\"Missing subject\");\n }\n\n assert(typeof params.applicationUri === \"string\");\n assert(Array.isArray(params.dns));\n\n // xx no key size in self-signed assert(params.keySize == 2048 || params.keySize == 4096);\n\n // processAltNames(params);\n adjustDate(params);\n assert(Object.prototype.hasOwnProperty.call(params, \"validity\"));\n\n let subject: Subject | string = new Subject(params.subject);\n subject = subject.toString();\n\n // xx const certificateRequestFilename = certificate + \".csr\";\n const purpose = params.purpose;\n\n displayTitle(\"Generate a certificate request\");\n\n const privateKeyPem = await fs.promises.readFile(params.privateKey, \"utf-8\");\n const privateKey = await pemToPrivateKey(privateKeyPem);\n\n const { cert } = await createSelfSignedCertificate1({\n privateKey,\n notBefore: params.startDate,\n notAfter: params.endDate,\n validity: params.validity,\n dns: params.dns,\n ip: params.ip,\n subject,\n applicationUri: params.applicationUri,\n purpose\n });\n await fs.promises.writeFile(certificate, cert, \"utf-8\");\n}\n\nexport async function createSelfSignedCertificate(\n certificate: string,\n params: CreateSelfSignCertificateWithConfigParam\n): Promise<void> {\n await createSelfSignedCertificateAsync(certificate, params);\n}\n","const config =\n \"##################################################################################################\\n\" +\n \"## SIMPLE OPENSSL CONFIG FILE FOR SELF-SIGNED CERTIFICATE GENERATION\\n\" +\n \"################################################################################################################\\n\" +\n \"\\n\" +\n \"distinguished_name = req_distinguished_name\\n\" +\n \"default_md = sha1\\n\" +\n \"\\n\" +\n \"default_md = sha256 # The default digest algorithm\\n\" +\n \"\\n\" +\n \"[ v3_ca ]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid:always,issuer:always\\n\" +\n \"\\n\" +\n \"# authorityKeyIdentifier = keyid\\n\" +\n \"basicConstraints = CA:TRUE\\n\" +\n \"keyUsage = critical, cRLSign, keyCertSign\\n\" +\n 'nsComment = \"Self-signed Certificate for CA generated by Node-OPCUA Certificate utility\"\\n' +\n \"#nsCertType = sslCA, emailCA\\n\" +\n \"#subjectAltName = email:copy\\n\" +\n \"#issuerAltName = issuer:copy\\n\" +\n \"#obj = DER:02:03\\n\" +\n \"# crlDistributionPoints = @crl_info\\n\" +\n \"# [ crl_info ]\\n\" +\n \"# URI.0 = http://localhost:8900/crl.pem\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"\\n\" +\n \"[ req ]\\n\" +\n \"days = 390\\n\" +\n \"req_extensions = v3_req\\n\" +\n \"x509_extensions = v3_ca\\n\" +\n \"\\n\" +\n \"[v3_req]\\n\" +\n \"basicConstraints = CA:false\\n\" +\n \"keyUsage = critical, cRLSign, keyCertSign\\n\" +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"\\n\" +\n \"[ v3_ca_signed]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid,issuer\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign\\n\" +\n \"extendedKeyUsage = clientAuth,serverAuth \\n\" +\n 'nsComment = \"certificate generated by Node-OPCUA Certificate utility and signed by a CA\"\\n' +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"[ v3_selfsigned]\\n\" +\n \"subjectKeyIdentifier = hash\\n\" +\n \"authorityKeyIdentifier = keyid,issuer\\n\" +\n \"basicConstraints = critical, CA:FALSE\\n\" +\n \"keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign\\n\" +\n \"extendedKeyUsage = clientAuth,serverAuth \\n\" +\n 'nsComment = \"Self-signed certificate generated by Node-OPCUA Certificate utility\"\\n' +\n \"subjectAltName = $ENV::ALTNAME\\n\" +\n \"[ req_distinguished_name ]\\n\" +\n \"countryName = Country Name (2 letter code)\\n\" +\n \"countryName_default = FR\\n\" +\n \"countryName_min = 2\\n\" +\n \"countryName_max = 2\\n\" +\n \"# stateOrProvinceName = State or Province Name (full name)\\n\" +\n \"# stateOrProvinceName_default = Ile de France\\n\" +\n \"# localityName = Locality Name (city, district)\\n\" +\n \"# localityName_default = Paris\\n\" +\n \"organizationName = Organization Name (company)\\n\" +\n \"organizationName_default = NodeOPCUA\\n\" +\n \"# organizationalUnitName = Organizational Unit Name (department, division)\\n\" +\n \"# organizationalUnitName_default = R&D\\n\" +\n \"commonName = Common Name (hostname, FQDN, IP, or your name)\\n\" +\n \"commonName_max = 256\\n\" +\n \"commonName_default = NodeOPCUA\\n\" +\n \"# emailAddress = Email Address\\n\" +\n \"# emailAddress_max = 40\\n\" +\n \"# emailAddress_default = node-opcua (at) node-opcua (dot) com\\n\" +\n \"subjectAltName = $ENV::ALTNAME\";\n\nexport default config;\n"],"mappings":"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","names":["import_node_assert","import_node_fs","import_node_path","import_chalk","import_node_opcua_crypto","assert","import_node_assert","fs","chalk","path","assert","import_chalk","chalk","import_node_assert","import_node_fs","import_node_path","import_node_assert","import_node_child_process","import_node_fs","import_node_os","import_byline","import_chalk","import_node_fs","import_node_path","import_chalk","doDebug","url","chalk","child_process","byline","quote","path","os","fs","opensslFolder","opensslExecPath","ProgressBar","wget","yauzl","execute","chalk","child_process","byline","os","fs","assert","chalk","execute","import_node_assert","import_node_fs","import_node_path","path","fs","n","assert","s","assert","fs","n","q","n","assert","fs","path","config","n","q","assert","path","fs","chalk","dns","import_node_assert","import_node_fs","import_node_os","import_node_path","import_chalk","import_node_opcua_crypto","import_node_assert","assert","import_node_os","os","dns","import_node_fs","import_node_path","import_chalk","import_node_opcua_crypto","import_node_assert","import_node_fs","import_node_opcua_crypto","assert","fs","import_node_assert","import_node_fs","import_node_opcua_crypto","assert","fs","createSelfSignedCertificate1","config","fs","VerificationStatus","fingerprint","CertificateManagerState","path","chalk","today","chokidar","construct_CertificateAuthority","assert","fs","path","default_config_template","assert","fqdn","os","chalk","dns","applicationUri","ip","createSelfSignedCertificate","construct_CertificateAuthority","commandLineUsage","commandLineArgs","local_argv"]}