node-opcua-pki 6.12.0 → 6.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/pki.mjs +92 -49
- package/dist/bin/pki.mjs.map +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +94 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +93 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -771,6 +771,7 @@ declare enum VerificationStatus {
|
|
|
771
771
|
/** Validation OK. */
|
|
772
772
|
Good = "Good"
|
|
773
773
|
}
|
|
774
|
+
declare function coerceCertificateChain(certificate: Certificate | Certificate[]): Certificate[];
|
|
774
775
|
declare function makeFingerprint(certificate: Certificate | Certificate[] | CertificateRevocationList): string;
|
|
775
776
|
/**
|
|
776
777
|
* Check if the provided certificate acts as an issuer (CA)
|
|
@@ -918,15 +919,15 @@ declare class CertificateManager extends EventEmitter {
|
|
|
918
919
|
/**
|
|
919
920
|
* Move a certificate to the rejected store.
|
|
920
921
|
* If the certificate was previously trusted, it will be removed from the trusted folder.
|
|
921
|
-
* @param
|
|
922
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
922
923
|
*/
|
|
923
|
-
rejectCertificate(
|
|
924
|
+
rejectCertificate(certificateOrChain: Certificate | Certificate[]): Promise<void>;
|
|
924
925
|
/**
|
|
925
926
|
* Move a certificate to the trusted store.
|
|
926
927
|
* If the certificate was previously rejected, it will be removed from the rejected folder.
|
|
927
|
-
* @param
|
|
928
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
928
929
|
*/
|
|
929
|
-
trustCertificate(
|
|
930
|
+
trustCertificate(certificateOrChain: Certificate | Certificate[]): Promise<void>;
|
|
930
931
|
/**
|
|
931
932
|
* Check whether the trusted certificate store is empty.
|
|
932
933
|
*
|
|
@@ -961,7 +962,7 @@ declare class CertificateManager extends EventEmitter {
|
|
|
961
962
|
* @returns `"Good"` if trusted, `"BadCertificateUntrusted"` if rejected/unknown,
|
|
962
963
|
* or `"BadCertificateInvalid"` if the certificate cannot be parsed.
|
|
963
964
|
*/
|
|
964
|
-
isCertificateTrusted(
|
|
965
|
+
isCertificateTrusted(certificateOrCertificateChain: Certificate | Certificate[]): Promise<"Good" | "BadCertificateUntrusted" | "BadCertificateInvalid">;
|
|
965
966
|
/**
|
|
966
967
|
* Internal verification hook called by {@link verifyCertificate}.
|
|
967
968
|
*
|
|
@@ -1304,4 +1305,4 @@ declare function dumpPFX(pfxFile: Filename, passphrase?: string): Promise<string
|
|
|
1304
1305
|
*/
|
|
1305
1306
|
declare function install_prerequisite(): Promise<string>;
|
|
1306
1307
|
|
|
1307
|
-
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
|
1308
|
+
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, coerceCertificateChain, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
package/dist/index.d.ts
CHANGED
|
@@ -771,6 +771,7 @@ declare enum VerificationStatus {
|
|
|
771
771
|
/** Validation OK. */
|
|
772
772
|
Good = "Good"
|
|
773
773
|
}
|
|
774
|
+
declare function coerceCertificateChain(certificate: Certificate | Certificate[]): Certificate[];
|
|
774
775
|
declare function makeFingerprint(certificate: Certificate | Certificate[] | CertificateRevocationList): string;
|
|
775
776
|
/**
|
|
776
777
|
* Check if the provided certificate acts as an issuer (CA)
|
|
@@ -918,15 +919,15 @@ declare class CertificateManager extends EventEmitter {
|
|
|
918
919
|
/**
|
|
919
920
|
* Move a certificate to the rejected store.
|
|
920
921
|
* If the certificate was previously trusted, it will be removed from the trusted folder.
|
|
921
|
-
* @param
|
|
922
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
922
923
|
*/
|
|
923
|
-
rejectCertificate(
|
|
924
|
+
rejectCertificate(certificateOrChain: Certificate | Certificate[]): Promise<void>;
|
|
924
925
|
/**
|
|
925
926
|
* Move a certificate to the trusted store.
|
|
926
927
|
* If the certificate was previously rejected, it will be removed from the rejected folder.
|
|
927
|
-
* @param
|
|
928
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
928
929
|
*/
|
|
929
|
-
trustCertificate(
|
|
930
|
+
trustCertificate(certificateOrChain: Certificate | Certificate[]): Promise<void>;
|
|
930
931
|
/**
|
|
931
932
|
* Check whether the trusted certificate store is empty.
|
|
932
933
|
*
|
|
@@ -961,7 +962,7 @@ declare class CertificateManager extends EventEmitter {
|
|
|
961
962
|
* @returns `"Good"` if trusted, `"BadCertificateUntrusted"` if rejected/unknown,
|
|
962
963
|
* or `"BadCertificateInvalid"` if the certificate cannot be parsed.
|
|
963
964
|
*/
|
|
964
|
-
isCertificateTrusted(
|
|
965
|
+
isCertificateTrusted(certificateOrCertificateChain: Certificate | Certificate[]): Promise<"Good" | "BadCertificateUntrusted" | "BadCertificateInvalid">;
|
|
965
966
|
/**
|
|
966
967
|
* Internal verification hook called by {@link verifyCertificate}.
|
|
967
968
|
*
|
|
@@ -1304,4 +1305,4 @@ declare function dumpPFX(pfxFile: Filename, passphrase?: string): Promise<string
|
|
|
1304
1305
|
*/
|
|
1305
1306
|
declare function install_prerequisite(): Promise<string>;
|
|
1306
1307
|
|
|
1307
|
-
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
|
1308
|
+
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, coerceCertificateChain, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ __export(lib_exports, {
|
|
|
37
37
|
VerificationStatus: () => VerificationStatus,
|
|
38
38
|
adjustApplicationUri: () => adjustApplicationUri,
|
|
39
39
|
adjustDate: () => adjustDate,
|
|
40
|
+
coerceCertificateChain: () => coerceCertificateChain,
|
|
40
41
|
convertPFXtoPEM: () => convertPFXtoPEM,
|
|
41
42
|
createPFX: () => createPFX,
|
|
42
43
|
dumpPFX: () => dumpPFX,
|
|
@@ -744,7 +745,7 @@ async function createCertificateSigningRequestWithOpenSSL(certificateSigningRequ
|
|
|
744
745
|
}
|
|
745
746
|
|
|
746
747
|
// packages/node-opcua-pki/lib/pki/templates/simple_config_template.cnf.ts
|
|
747
|
-
var 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,
|
|
748
|
+
var 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';
|
|
748
749
|
var simple_config_template_cnf_default = config;
|
|
749
750
|
|
|
750
751
|
// packages/node-opcua-pki/lib/ca/templates/ca_config_template.cnf.ts
|
|
@@ -839,7 +840,7 @@ nsComment = ''OpenSSL Generated Certificate''
|
|
|
839
840
|
#nsRenewalUrl =
|
|
840
841
|
#nsCaPolicyUrl =
|
|
841
842
|
#nsSslServerName =
|
|
842
|
-
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement
|
|
843
|
+
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement
|
|
843
844
|
extendedKeyUsage = critical,serverAuth ,clientAuth
|
|
844
845
|
|
|
845
846
|
[ v3_req ]
|
|
@@ -1930,8 +1931,17 @@ var VerificationStatus = /* @__PURE__ */ ((VerificationStatus2) => {
|
|
|
1930
1931
|
VerificationStatus2["Good"] = "Good";
|
|
1931
1932
|
return VerificationStatus2;
|
|
1932
1933
|
})(VerificationStatus || {});
|
|
1934
|
+
function coerceCertificateChain(certificate) {
|
|
1935
|
+
if (Array.isArray(certificate)) {
|
|
1936
|
+
if (certificate.length === 0) return [];
|
|
1937
|
+
return certificate.reduce((acc, cert) => {
|
|
1938
|
+
return acc.concat((0, import_node_opcua_crypto5.split_der)(cert));
|
|
1939
|
+
}, []);
|
|
1940
|
+
}
|
|
1941
|
+
return (0, import_node_opcua_crypto5.split_der)(certificate);
|
|
1942
|
+
}
|
|
1933
1943
|
function makeFingerprint(certificate) {
|
|
1934
|
-
const chain =
|
|
1944
|
+
const chain = coerceCertificateChain(certificate);
|
|
1935
1945
|
return (0, import_node_opcua_crypto5.makeSHA1Thumbprint)(chain[0]).toString("hex");
|
|
1936
1946
|
}
|
|
1937
1947
|
function short(stringToShorten) {
|
|
@@ -1939,9 +1949,10 @@ function short(stringToShorten) {
|
|
|
1939
1949
|
}
|
|
1940
1950
|
var forbiddenChars = /[\x00-\x1F<>:"/\\|?*]/g;
|
|
1941
1951
|
function buildIdealCertificateName(certificate) {
|
|
1942
|
-
const
|
|
1952
|
+
const chain = coerceCertificateChain(certificate);
|
|
1953
|
+
const fingerprint = makeFingerprint(chain);
|
|
1943
1954
|
try {
|
|
1944
|
-
const commonName = (0, import_node_opcua_crypto5.exploreCertificate)(
|
|
1955
|
+
const commonName = (0, import_node_opcua_crypto5.exploreCertificate)(chain[0]).tbsCertificate.subject.commonName || "";
|
|
1945
1956
|
const sanitizedCommonName = commonName.replace(forbiddenChars, "_");
|
|
1946
1957
|
return `${sanitizedCommonName}[${fingerprint}]`;
|
|
1947
1958
|
} catch (_err) {
|
|
@@ -2003,7 +2014,8 @@ function isRootIssuer(certificate) {
|
|
|
2003
2014
|
}
|
|
2004
2015
|
}
|
|
2005
2016
|
function findIssuerCertificateInChain(certificate, chain) {
|
|
2006
|
-
const
|
|
2017
|
+
const coercedCertificate = coerceCertificateChain(certificate);
|
|
2018
|
+
const firstCertificate = coercedCertificate[0];
|
|
2007
2019
|
if (!firstCertificate) {
|
|
2008
2020
|
return null;
|
|
2009
2021
|
}
|
|
@@ -2016,7 +2028,8 @@ function findIssuerCertificateInChain(certificate, chain) {
|
|
|
2016
2028
|
debugLog("Certificate has no extension 3");
|
|
2017
2029
|
return null;
|
|
2018
2030
|
}
|
|
2019
|
-
const
|
|
2031
|
+
const coercedChain = coerceCertificateChain(chain);
|
|
2032
|
+
const potentialIssuers = coercedChain.filter((c) => {
|
|
2020
2033
|
const info = (0, import_node_opcua_crypto5.exploreCertificate)(c);
|
|
2021
2034
|
return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;
|
|
2022
2035
|
});
|
|
@@ -2186,18 +2199,18 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2186
2199
|
/**
|
|
2187
2200
|
* Move a certificate to the rejected store.
|
|
2188
2201
|
* If the certificate was previously trusted, it will be removed from the trusted folder.
|
|
2189
|
-
* @param
|
|
2202
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
2190
2203
|
*/
|
|
2191
|
-
async rejectCertificate(
|
|
2192
|
-
await this.#moveCertificate(
|
|
2204
|
+
async rejectCertificate(certificateOrChain) {
|
|
2205
|
+
await this.#moveCertificate(certificateOrChain, "rejected");
|
|
2193
2206
|
}
|
|
2194
2207
|
/**
|
|
2195
2208
|
* Move a certificate to the trusted store.
|
|
2196
2209
|
* If the certificate was previously rejected, it will be removed from the rejected folder.
|
|
2197
|
-
* @param
|
|
2210
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
2198
2211
|
*/
|
|
2199
|
-
async trustCertificate(
|
|
2200
|
-
await this.#moveCertificate(
|
|
2212
|
+
async trustCertificate(certificateOrChain) {
|
|
2213
|
+
await this.#moveCertificate(certificateOrChain, "trusted");
|
|
2201
2214
|
}
|
|
2202
2215
|
/**
|
|
2203
2216
|
* Check whether the trusted certificate store is empty.
|
|
@@ -2251,37 +2264,46 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2251
2264
|
* @returns `"Good"` if trusted, `"BadCertificateUntrusted"` if rejected/unknown,
|
|
2252
2265
|
* or `"BadCertificateInvalid"` if the certificate cannot be parsed.
|
|
2253
2266
|
*/
|
|
2254
|
-
async isCertificateTrusted(
|
|
2255
|
-
let fingerprint;
|
|
2267
|
+
async isCertificateTrusted(certificateOrCertificateChain) {
|
|
2256
2268
|
try {
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
if (this.#thumbs.trusted.has(fingerprint)) {
|
|
2262
|
-
return "Good";
|
|
2263
|
-
}
|
|
2264
|
-
if (!this.#thumbs.rejected.has(fingerprint)) {
|
|
2265
|
-
if (!this.untrustUnknownCertificate) {
|
|
2266
|
-
return "Good";
|
|
2269
|
+
const chain = coerceCertificateChain(certificateOrCertificateChain);
|
|
2270
|
+
const leafCertificate = chain[0];
|
|
2271
|
+
if (chain.length < 1) {
|
|
2272
|
+
return "BadCertificateInvalid";
|
|
2267
2273
|
}
|
|
2274
|
+
let fingerprint;
|
|
2268
2275
|
try {
|
|
2269
|
-
(0
|
|
2276
|
+
fingerprint = makeFingerprint(chain[0]);
|
|
2270
2277
|
} catch (_err) {
|
|
2271
2278
|
return "BadCertificateInvalid";
|
|
2272
2279
|
}
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
this.#thumbs.rejected.
|
|
2280
|
+
if (this.#thumbs.trusted.has(fingerprint)) {
|
|
2281
|
+
return "Good";
|
|
2282
|
+
}
|
|
2283
|
+
if (!this.#thumbs.rejected.has(fingerprint)) {
|
|
2284
|
+
if (!this.untrustUnknownCertificate) {
|
|
2285
|
+
return "Good";
|
|
2286
|
+
}
|
|
2287
|
+
try {
|
|
2288
|
+
(0, import_node_opcua_crypto5.exploreCertificateInfo)(chain[0]);
|
|
2289
|
+
} catch (_err) {
|
|
2290
|
+
return "BadCertificateInvalid";
|
|
2291
|
+
}
|
|
2292
|
+
const filename = import_node_path6.default.join(this.rejectedFolder, `${buildIdealCertificateName(leafCertificate)}.pem`);
|
|
2293
|
+
debugLog("certificate has never been seen before and is now rejected (untrusted) ", filename);
|
|
2294
|
+
await fsWriteFile(filename, (0, import_node_opcua_crypto5.toPem)(chain, "CERTIFICATE"));
|
|
2295
|
+
this.#thumbs.rejected.set(fingerprint, { certificate: leafCertificate, filename });
|
|
2296
|
+
}
|
|
2297
|
+
return "BadCertificateUntrusted";
|
|
2298
|
+
} catch (_err) {
|
|
2299
|
+
return "BadCertificateInvalid";
|
|
2277
2300
|
}
|
|
2278
|
-
return "BadCertificateUntrusted";
|
|
2279
2301
|
}
|
|
2280
2302
|
async #innerVerifyCertificateAsync(certificateOrChain, _isIssuer, level, options) {
|
|
2281
2303
|
if (level >= 5) {
|
|
2282
2304
|
return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
|
|
2283
2305
|
}
|
|
2284
|
-
const chain =
|
|
2306
|
+
const chain = coerceCertificateChain(certificateOrChain);
|
|
2285
2307
|
debugLog("NB CERTIFICATE IN CHAIN = ", chain.length);
|
|
2286
2308
|
const info = (0, import_node_opcua_crypto5.exploreCertificate)(chain[0]);
|
|
2287
2309
|
let hasValidIssuer = false;
|
|
@@ -2336,7 +2358,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2336
2358
|
return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
|
|
2337
2359
|
}
|
|
2338
2360
|
hasValidIssuer = true;
|
|
2339
|
-
let revokedStatus = await this.isCertificateRevoked(
|
|
2361
|
+
let revokedStatus = await this.isCertificateRevoked(chain, issuerCertificate);
|
|
2340
2362
|
if (revokedStatus === "BadCertificateRevocationUnknown" /* BadCertificateRevocationUnknown */) {
|
|
2341
2363
|
if (options?.ignoreMissingRevocationList) {
|
|
2342
2364
|
revokedStatus = "Good" /* Good */;
|
|
@@ -2361,11 +2383,11 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2361
2383
|
debugLog("Self-signed Certificate signature is not valid");
|
|
2362
2384
|
return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
|
|
2363
2385
|
}
|
|
2364
|
-
const revokedStatus = await this.isCertificateRevoked(
|
|
2386
|
+
const revokedStatus = await this.isCertificateRevoked(chain);
|
|
2365
2387
|
debugLog("revokedStatus of self signed certificate:", revokedStatus);
|
|
2366
2388
|
}
|
|
2367
2389
|
}
|
|
2368
|
-
const status = await this.#checkRejectedOrTrusted(
|
|
2390
|
+
const status = await this.#checkRejectedOrTrusted(chain[0]);
|
|
2369
2391
|
if (status === "rejected") {
|
|
2370
2392
|
if (!(options.acceptCertificateWithValidIssuerChain && hasValidIssuer && hasTrustedIssuer)) {
|
|
2371
2393
|
return "BadCertificateUntrusted" /* BadCertificateUntrusted */;
|
|
@@ -2423,17 +2445,15 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2423
2445
|
* @returns the verification status code
|
|
2424
2446
|
*/
|
|
2425
2447
|
async verifyCertificateAsync(certificate, options) {
|
|
2426
|
-
|
|
2448
|
+
const chain = coerceCertificateChain(certificate);
|
|
2449
|
+
for (const element of chain) {
|
|
2427
2450
|
try {
|
|
2428
|
-
|
|
2429
|
-
for (const element of derElements) {
|
|
2430
|
-
(0, import_node_opcua_crypto5.exploreCertificateInfo)(element);
|
|
2431
|
-
}
|
|
2451
|
+
(0, import_node_opcua_crypto5.exploreCertificateInfo)(element);
|
|
2432
2452
|
} catch (_err) {
|
|
2433
2453
|
return "BadCertificateInvalid" /* BadCertificateInvalid */;
|
|
2434
2454
|
}
|
|
2435
2455
|
}
|
|
2436
|
-
const status1 = await this.#innerVerifyCertificateAsync(
|
|
2456
|
+
const status1 = await this.#innerVerifyCertificateAsync(chain, false, 0, options);
|
|
2437
2457
|
return status1;
|
|
2438
2458
|
}
|
|
2439
2459
|
/**
|
|
@@ -2863,7 +2883,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2863
2883
|
async #addTrustedCertificateFromChainImpl(certificateChain) {
|
|
2864
2884
|
let certificates;
|
|
2865
2885
|
try {
|
|
2866
|
-
certificates =
|
|
2886
|
+
certificates = coerceCertificateChain(certificateChain);
|
|
2867
2887
|
} catch (_err) {
|
|
2868
2888
|
return "BadCertificateInvalid" /* BadCertificateInvalid */;
|
|
2869
2889
|
}
|
|
@@ -2947,7 +2967,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2947
2967
|
return "BadCertificateInvalid" /* BadCertificateInvalid */;
|
|
2948
2968
|
}
|
|
2949
2969
|
}
|
|
2950
|
-
await this.trustCertificate(
|
|
2970
|
+
await this.trustCertificate(certificates);
|
|
2951
2971
|
return "Good" /* Good */;
|
|
2952
2972
|
}
|
|
2953
2973
|
/**
|
|
@@ -2990,7 +3010,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2990
3010
|
*
|
|
2991
3011
|
*/
|
|
2992
3012
|
async findIssuerCertificate(certificate) {
|
|
2993
|
-
const firstCertificate =
|
|
3013
|
+
const firstCertificate = coerceCertificateChain(certificate)[0];
|
|
2994
3014
|
const certInfo = (0, import_node_opcua_crypto5.exploreCertificate)(firstCertificate);
|
|
2995
3015
|
if (isSelfSigned2(certInfo)) {
|
|
2996
3016
|
return firstCertificate;
|
|
@@ -3027,7 +3047,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3027
3047
|
* @private
|
|
3028
3048
|
*/
|
|
3029
3049
|
async #checkRejectedOrTrusted(certificate) {
|
|
3030
|
-
const firstCertificate =
|
|
3050
|
+
const firstCertificate = coerceCertificateChain(certificate)[0];
|
|
3031
3051
|
const fingerprint = makeFingerprint(firstCertificate);
|
|
3032
3052
|
debugLog("#checkRejectedOrTrusted fingerprint ", short(fingerprint));
|
|
3033
3053
|
await this.#readCertificates();
|
|
@@ -3039,12 +3059,14 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3039
3059
|
}
|
|
3040
3060
|
return "unknown";
|
|
3041
3061
|
}
|
|
3042
|
-
async #moveCertificate(
|
|
3062
|
+
async #moveCertificate(certificateOrChain, newStatus) {
|
|
3043
3063
|
await this.withLock2(async () => {
|
|
3064
|
+
const chain = coerceCertificateChain(certificateOrChain);
|
|
3065
|
+
const certificate = chain[0];
|
|
3044
3066
|
const fingerprint = makeFingerprint(certificate);
|
|
3045
3067
|
let status = await this.#checkRejectedOrTrusted(certificate);
|
|
3046
3068
|
if (status === "unknown") {
|
|
3047
|
-
const pem = (0, import_node_opcua_crypto5.toPem)(
|
|
3069
|
+
const pem = (0, import_node_opcua_crypto5.toPem)(chain, "CERTIFICATE");
|
|
3048
3070
|
const filename = import_node_path6.default.join(this.rejectedFolder, `${buildIdealCertificateName(certificate)}.pem`);
|
|
3049
3071
|
await import_node_fs10.default.promises.writeFile(filename, pem);
|
|
3050
3072
|
this.#thumbs.rejected.set(fingerprint, { certificate, filename });
|
|
@@ -3094,13 +3116,17 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3094
3116
|
* found.
|
|
3095
3117
|
*/
|
|
3096
3118
|
async isCertificateRevoked(certificate, issuerCertificate) {
|
|
3097
|
-
const
|
|
3119
|
+
const chain = coerceCertificateChain(certificate);
|
|
3120
|
+
const firstCertificate = chain[0];
|
|
3098
3121
|
if (isSelfSigned3(firstCertificate)) {
|
|
3099
3122
|
return "Good" /* Good */;
|
|
3100
3123
|
}
|
|
3101
3124
|
if (!issuerCertificate) {
|
|
3102
3125
|
issuerCertificate = await this.findIssuerCertificate(firstCertificate);
|
|
3103
3126
|
}
|
|
3127
|
+
if (!issuerCertificate) {
|
|
3128
|
+
issuerCertificate = findIssuerCertificateInChain(firstCertificate, chain);
|
|
3129
|
+
}
|
|
3104
3130
|
if (!issuerCertificate) {
|
|
3105
3131
|
return "BadCertificateChainIncomplete" /* BadCertificateChainIncomplete */;
|
|
3106
3132
|
}
|
|
@@ -3227,7 +3253,25 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3227
3253
|
try {
|
|
3228
3254
|
const stat = await import_node_fs10.default.promises.stat(filename);
|
|
3229
3255
|
if (!stat.isFile()) continue;
|
|
3230
|
-
const
|
|
3256
|
+
const certs = await (0, import_node_opcua_crypto5.readCertificateChainAsync)(filename);
|
|
3257
|
+
if (certs.length === 0) continue;
|
|
3258
|
+
const certificate = certs[0];
|
|
3259
|
+
if (certs.length > 1) {
|
|
3260
|
+
try {
|
|
3261
|
+
await import_node_fs10.default.promises.writeFile(filename, (0, import_node_opcua_crypto5.toPem)(certs, "CERTIFICATE"), "ascii");
|
|
3262
|
+
} catch (writeErr) {
|
|
3263
|
+
debugLog(`scanCertFolder: could not rewrite legacy PEM ${filename} (read-only fs?)`, writeErr);
|
|
3264
|
+
}
|
|
3265
|
+
for (let i = 1; i < certs.length; i++) {
|
|
3266
|
+
if (isIssuer(certs[i])) {
|
|
3267
|
+
try {
|
|
3268
|
+
await this.addIssuer(certs[i]);
|
|
3269
|
+
} catch (issuerErr) {
|
|
3270
|
+
debugLog(`scanCertFolder: could not auto-register issuer from ${filename}`, issuerErr);
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3231
3275
|
const info = (0, import_node_opcua_crypto5.exploreCertificate)(certificate);
|
|
3232
3276
|
const fingerprint = makeFingerprint(certificate);
|
|
3233
3277
|
index.set(fingerprint, { certificate, filename, info });
|
|
@@ -3380,6 +3424,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3380
3424
|
VerificationStatus,
|
|
3381
3425
|
adjustApplicationUri,
|
|
3382
3426
|
adjustDate,
|
|
3427
|
+
coerceCertificateChain,
|
|
3383
3428
|
convertPFXtoPEM,
|
|
3384
3429
|
createPFX,
|
|
3385
3430
|
dumpPFX,
|