node-opcua-pki 6.12.0 → 6.12.1

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/bin/pki.mjs CHANGED
@@ -336,7 +336,7 @@ var init_simple_config_template_cnf = __esm({
336
336
  "packages/node-opcua-pki/lib/pki/templates/simple_config_template.cnf.ts"() {
337
337
  "use strict";
338
338
  init_esm_shims();
339
- config = '##################################################################################################\n## SIMPLE OPENSSL CONFIG FILE FOR SELF-SIGNED CERTIFICATE GENERATION\n################################################################################################################\n\ndistinguished_name = req_distinguished_name\ndefault_md = sha1\n\ndefault_md = sha256 # The default digest algorithm\n\n[ v3_ca ]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid:always,issuer:always\n\n# authorityKeyIdentifier = keyid\nbasicConstraints = CA:TRUE\nkeyUsage = critical, cRLSign, keyCertSign\nnsComment = "Self-signed Certificate for CA generated by Node-OPCUA Certificate utility"\n#nsCertType = sslCA, emailCA\n#subjectAltName = email:copy\n#issuerAltName = issuer:copy\n#obj = DER:02:03\n# crlDistributionPoints = @crl_info\n# [ crl_info ]\n# URI.0 = http://localhost:8900/crl.pem\nsubjectAltName = $ENV::ALTNAME\n\n[ req ]\ndays = 390\nreq_extensions = v3_req\nx509_extensions = v3_ca\n\n[v3_req]\nbasicConstraints = CA:false\nkeyUsage = critical, cRLSign, keyCertSign\nsubjectAltName = $ENV::ALTNAME\n\n[ v3_ca_signed]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid,issuer\nbasicConstraints = critical, CA:FALSE\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign\nextendedKeyUsage = clientAuth,serverAuth \nnsComment = "certificate generated by Node-OPCUA Certificate utility and signed by a CA"\nsubjectAltName = $ENV::ALTNAME\n[ v3_selfsigned]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid,issuer\nbasicConstraints = critical, CA:FALSE\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign\nextendedKeyUsage = clientAuth,serverAuth \nnsComment = "Self-signed certificate generated by Node-OPCUA Certificate utility"\nsubjectAltName = $ENV::ALTNAME\n[ req_distinguished_name ]\ncountryName = Country Name (2 letter code)\ncountryName_default = FR\ncountryName_min = 2\ncountryName_max = 2\n# stateOrProvinceName = State or Province Name (full name)\n# stateOrProvinceName_default = Ile de France\n# localityName = Locality Name (city, district)\n# localityName_default = Paris\norganizationName = Organization Name (company)\norganizationName_default = NodeOPCUA\n# organizationalUnitName = Organizational Unit Name (department, division)\n# organizationalUnitName_default = R&D\ncommonName = Common Name (hostname, FQDN, IP, or your name)\ncommonName_max = 256\ncommonName_default = NodeOPCUA\n# emailAddress = Email Address\n# emailAddress_max = 40\n# emailAddress_default = node-opcua (at) node-opcua (dot) com\nsubjectAltName = $ENV::ALTNAME';
339
+ config = '##################################################################################################\n## SIMPLE OPENSSL CONFIG FILE FOR SELF-SIGNED CERTIFICATE GENERATION\n################################################################################################################\n\ndistinguished_name = req_distinguished_name\ndefault_md = sha1\n\ndefault_md = sha256 # The default digest algorithm\n\n[ v3_ca ]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid:always,issuer:always\n\n# authorityKeyIdentifier = keyid\nbasicConstraints = CA:TRUE\nkeyUsage = critical, cRLSign, keyCertSign\nnsComment = "Self-signed Certificate for CA generated by Node-OPCUA Certificate utility"\n#nsCertType = sslCA, emailCA\n#subjectAltName = email:copy\n#issuerAltName = issuer:copy\n#obj = DER:02:03\n# crlDistributionPoints = @crl_info\n# [ crl_info ]\n# URI.0 = http://localhost:8900/crl.pem\nsubjectAltName = $ENV::ALTNAME\n\n[ req ]\ndays = 390\nreq_extensions = v3_req\nx509_extensions = v3_ca\n\n[v3_req]\nbasicConstraints = CA:false\nkeyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment\nsubjectAltName = $ENV::ALTNAME\n\n[ v3_ca_signed]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid,issuer\nbasicConstraints = critical, CA:FALSE\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment\nextendedKeyUsage = clientAuth,serverAuth \nnsComment = "certificate generated by Node-OPCUA Certificate utility and signed by a CA"\nsubjectAltName = $ENV::ALTNAME\n[ v3_selfsigned]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid,issuer\nbasicConstraints = critical, CA:FALSE\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment\nextendedKeyUsage = clientAuth,serverAuth \nnsComment = "Self-signed certificate generated by Node-OPCUA Certificate utility"\nsubjectAltName = $ENV::ALTNAME\n[ req_distinguished_name ]\ncountryName = Country Name (2 letter code)\ncountryName_default = FR\ncountryName_min = 2\ncountryName_max = 2\n# stateOrProvinceName = State or Province Name (full name)\n# stateOrProvinceName_default = Ile de France\n# localityName = Locality Name (city, district)\n# localityName_default = Paris\norganizationName = Organization Name (company)\norganizationName_default = NodeOPCUA\n# organizationalUnitName = Organizational Unit Name (department, division)\n# organizationalUnitName_default = R&D\ncommonName = Common Name (hostname, FQDN, IP, or your name)\ncommonName_max = 256\ncommonName_default = NodeOPCUA\n# emailAddress = Email Address\n# emailAddress_max = 40\n# emailAddress_default = node-opcua (at) node-opcua (dot) com\nsubjectAltName = $ENV::ALTNAME';
340
340
  simple_config_template_cnf_default = config;
341
341
  }
342
342
  });
@@ -367,8 +367,17 @@ function getOrComputeInfo(entry) {
367
367
  }
368
368
  return entry.info;
369
369
  }
370
+ function coerceCertificateChain(certificate) {
371
+ if (Array.isArray(certificate)) {
372
+ if (certificate.length === 0) return [];
373
+ return certificate.reduce((acc, cert) => {
374
+ return acc.concat(split_der(cert));
375
+ }, []);
376
+ }
377
+ return split_der(certificate);
378
+ }
370
379
  function makeFingerprint(certificate) {
371
- const chain = Array.isArray(certificate) ? certificate : split_der(certificate);
380
+ const chain = coerceCertificateChain(certificate);
372
381
  return makeSHA1Thumbprint(chain[0]).toString("hex");
373
382
  }
374
383
  function short(stringToShorten) {
@@ -417,7 +426,8 @@ function isIssuer(certificate) {
417
426
  }
418
427
  }
419
428
  function findIssuerCertificateInChain(certificate, chain) {
420
- const firstCertificate = Array.isArray(certificate) ? certificate[0] : certificate;
429
+ const coercedCertificate = coerceCertificateChain(certificate);
430
+ const firstCertificate = coercedCertificate[0];
421
431
  if (!firstCertificate) {
422
432
  return null;
423
433
  }
@@ -430,7 +440,8 @@ function findIssuerCertificateInChain(certificate, chain) {
430
440
  debugLog("Certificate has no extension 3");
431
441
  return null;
432
442
  }
433
- const potentialIssuers = chain.filter((c) => {
443
+ const coercedChain = coerceCertificateChain(chain);
444
+ const potentialIssuers = coercedChain.filter((c) => {
434
445
  const info = exploreCertificate(c);
435
446
  return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;
436
447
  });
@@ -699,7 +710,7 @@ var init_certificate_manager = __esm({
699
710
  if (level >= 5) {
700
711
  return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
701
712
  }
702
- const chain = Array.isArray(certificateOrChain) ? certificateOrChain : [certificateOrChain];
713
+ const chain = coerceCertificateChain(certificateOrChain);
703
714
  debugLog("NB CERTIFICATE IN CHAIN = ", chain.length);
704
715
  const info = exploreCertificate(chain[0]);
705
716
  let hasValidIssuer = false;
@@ -754,7 +765,7 @@ var init_certificate_manager = __esm({
754
765
  return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
755
766
  }
756
767
  hasValidIssuer = true;
757
- let revokedStatus = await this.isCertificateRevoked(certificateOrChain);
768
+ let revokedStatus = await this.isCertificateRevoked(chain, issuerCertificate);
758
769
  if (revokedStatus === "BadCertificateRevocationUnknown" /* BadCertificateRevocationUnknown */) {
759
770
  if (options?.ignoreMissingRevocationList) {
760
771
  revokedStatus = "Good" /* Good */;
@@ -779,11 +790,11 @@ var init_certificate_manager = __esm({
779
790
  debugLog("Self-signed Certificate signature is not valid");
780
791
  return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
781
792
  }
782
- const revokedStatus = await this.isCertificateRevoked(certificateOrChain);
793
+ const revokedStatus = await this.isCertificateRevoked(chain);
783
794
  debugLog("revokedStatus of self signed certificate:", revokedStatus);
784
795
  }
785
796
  }
786
- const status = await this.#checkRejectedOrTrusted(certificateOrChain);
797
+ const status = await this.#checkRejectedOrTrusted(chain[0]);
787
798
  if (status === "rejected") {
788
799
  if (!(options.acceptCertificateWithValidIssuerChain && hasValidIssuer && hasTrustedIssuer)) {
789
800
  return "BadCertificateUntrusted" /* BadCertificateUntrusted */;
@@ -841,17 +852,15 @@ var init_certificate_manager = __esm({
841
852
  * @returns the verification status code
842
853
  */
843
854
  async verifyCertificateAsync(certificate, options) {
844
- if (!Array.isArray(certificate)) {
855
+ const chain = coerceCertificateChain(certificate);
856
+ for (const element of chain) {
845
857
  try {
846
- const derElements = split_der(certificate);
847
- for (const element of derElements) {
848
- exploreCertificateInfo(element);
849
- }
858
+ exploreCertificateInfo(element);
850
859
  } catch (_err) {
851
860
  return "BadCertificateInvalid" /* BadCertificateInvalid */;
852
861
  }
853
862
  }
854
- const status1 = await this.#innerVerifyCertificateAsync(certificate, false, 0, options);
863
+ const status1 = await this.#innerVerifyCertificateAsync(chain, false, 0, options);
855
864
  return status1;
856
865
  }
857
866
  /**
@@ -1281,7 +1290,7 @@ var init_certificate_manager = __esm({
1281
1290
  async #addTrustedCertificateFromChainImpl(certificateChain) {
1282
1291
  let certificates;
1283
1292
  try {
1284
- certificates = Array.isArray(certificateChain) ? certificateChain : split_der(certificateChain);
1293
+ certificates = coerceCertificateChain(certificateChain);
1285
1294
  } catch (_err) {
1286
1295
  return "BadCertificateInvalid" /* BadCertificateInvalid */;
1287
1296
  }
@@ -1408,7 +1417,7 @@ var init_certificate_manager = __esm({
1408
1417
  *
1409
1418
  */
1410
1419
  async findIssuerCertificate(certificate) {
1411
- const firstCertificate = Array.isArray(certificate) ? certificate[0] : certificate;
1420
+ const firstCertificate = coerceCertificateChain(certificate)[0];
1412
1421
  const certInfo = exploreCertificate(firstCertificate);
1413
1422
  if (isSelfSigned2(certInfo)) {
1414
1423
  return firstCertificate;
@@ -1445,7 +1454,7 @@ var init_certificate_manager = __esm({
1445
1454
  * @private
1446
1455
  */
1447
1456
  async #checkRejectedOrTrusted(certificate) {
1448
- const firstCertificate = Array.isArray(certificate) ? certificate[0] : certificate;
1457
+ const firstCertificate = coerceCertificateChain(certificate)[0];
1449
1458
  const fingerprint2 = makeFingerprint(firstCertificate);
1450
1459
  debugLog("#checkRejectedOrTrusted fingerprint ", short(fingerprint2));
1451
1460
  await this.#readCertificates();
@@ -1512,13 +1521,17 @@ var init_certificate_manager = __esm({
1512
1521
  * found.
1513
1522
  */
1514
1523
  async isCertificateRevoked(certificate, issuerCertificate) {
1515
- const firstCertificate = Array.isArray(certificate) ? certificate[0] : certificate;
1524
+ const chain = coerceCertificateChain(certificate);
1525
+ const firstCertificate = chain[0];
1516
1526
  if (isSelfSigned3(firstCertificate)) {
1517
1527
  return "Good" /* Good */;
1518
1528
  }
1519
1529
  if (!issuerCertificate) {
1520
1530
  issuerCertificate = await this.findIssuerCertificate(firstCertificate);
1521
1531
  }
1532
+ if (!issuerCertificate) {
1533
+ issuerCertificate = findIssuerCertificateInChain(firstCertificate, chain);
1534
+ }
1522
1535
  if (!issuerCertificate) {
1523
1536
  return "BadCertificateChainIncomplete" /* BadCertificateChainIncomplete */;
1524
1537
  }
@@ -2544,7 +2557,7 @@ nsComment = ''OpenSSL Generated Certificate''
2544
2557
  #nsRenewalUrl =
2545
2558
  #nsCaPolicyUrl =
2546
2559
  #nsSslServerName =
2547
- keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign
2560
+ keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement
2548
2561
  extendedKeyUsage = critical,serverAuth ,clientAuth
2549
2562
 
2550
2563
  [ v3_req ]