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.mjs
CHANGED
|
@@ -700,7 +700,7 @@ async function createCertificateSigningRequestWithOpenSSL(certificateSigningRequ
|
|
|
700
700
|
}
|
|
701
701
|
|
|
702
702
|
// packages/node-opcua-pki/lib/pki/templates/simple_config_template.cnf.ts
|
|
703
|
-
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,
|
|
703
|
+
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';
|
|
704
704
|
var simple_config_template_cnf_default = config;
|
|
705
705
|
|
|
706
706
|
// packages/node-opcua-pki/lib/ca/templates/ca_config_template.cnf.ts
|
|
@@ -795,7 +795,7 @@ nsComment = ''OpenSSL Generated Certificate''
|
|
|
795
795
|
#nsRenewalUrl =
|
|
796
796
|
#nsCaPolicyUrl =
|
|
797
797
|
#nsSslServerName =
|
|
798
|
-
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement
|
|
798
|
+
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement
|
|
799
799
|
extendedKeyUsage = critical,serverAuth ,clientAuth
|
|
800
800
|
|
|
801
801
|
[ v3_req ]
|
|
@@ -1903,8 +1903,17 @@ var VerificationStatus = /* @__PURE__ */ ((VerificationStatus2) => {
|
|
|
1903
1903
|
VerificationStatus2["Good"] = "Good";
|
|
1904
1904
|
return VerificationStatus2;
|
|
1905
1905
|
})(VerificationStatus || {});
|
|
1906
|
+
function coerceCertificateChain(certificate) {
|
|
1907
|
+
if (Array.isArray(certificate)) {
|
|
1908
|
+
if (certificate.length === 0) return [];
|
|
1909
|
+
return certificate.reduce((acc, cert) => {
|
|
1910
|
+
return acc.concat(split_der(cert));
|
|
1911
|
+
}, []);
|
|
1912
|
+
}
|
|
1913
|
+
return split_der(certificate);
|
|
1914
|
+
}
|
|
1906
1915
|
function makeFingerprint(certificate) {
|
|
1907
|
-
const chain =
|
|
1916
|
+
const chain = coerceCertificateChain(certificate);
|
|
1908
1917
|
return makeSHA1Thumbprint(chain[0]).toString("hex");
|
|
1909
1918
|
}
|
|
1910
1919
|
function short(stringToShorten) {
|
|
@@ -1912,9 +1921,10 @@ function short(stringToShorten) {
|
|
|
1912
1921
|
}
|
|
1913
1922
|
var forbiddenChars = /[\x00-\x1F<>:"/\\|?*]/g;
|
|
1914
1923
|
function buildIdealCertificateName(certificate) {
|
|
1915
|
-
const
|
|
1924
|
+
const chain = coerceCertificateChain(certificate);
|
|
1925
|
+
const fingerprint = makeFingerprint(chain);
|
|
1916
1926
|
try {
|
|
1917
|
-
const commonName = exploreCertificate2(
|
|
1927
|
+
const commonName = exploreCertificate2(chain[0]).tbsCertificate.subject.commonName || "";
|
|
1918
1928
|
const sanitizedCommonName = commonName.replace(forbiddenChars, "_");
|
|
1919
1929
|
return `${sanitizedCommonName}[${fingerprint}]`;
|
|
1920
1930
|
} catch (_err) {
|
|
@@ -1976,7 +1986,8 @@ function isRootIssuer(certificate) {
|
|
|
1976
1986
|
}
|
|
1977
1987
|
}
|
|
1978
1988
|
function findIssuerCertificateInChain(certificate, chain) {
|
|
1979
|
-
const
|
|
1989
|
+
const coercedCertificate = coerceCertificateChain(certificate);
|
|
1990
|
+
const firstCertificate = coercedCertificate[0];
|
|
1980
1991
|
if (!firstCertificate) {
|
|
1981
1992
|
return null;
|
|
1982
1993
|
}
|
|
@@ -1989,7 +2000,8 @@ function findIssuerCertificateInChain(certificate, chain) {
|
|
|
1989
2000
|
debugLog("Certificate has no extension 3");
|
|
1990
2001
|
return null;
|
|
1991
2002
|
}
|
|
1992
|
-
const
|
|
2003
|
+
const coercedChain = coerceCertificateChain(chain);
|
|
2004
|
+
const potentialIssuers = coercedChain.filter((c) => {
|
|
1993
2005
|
const info = exploreCertificate2(c);
|
|
1994
2006
|
return info.tbsCertificate.extensions && info.tbsCertificate.extensions.subjectKeyIdentifier === wantedIssuerKey;
|
|
1995
2007
|
});
|
|
@@ -2159,18 +2171,18 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2159
2171
|
/**
|
|
2160
2172
|
* Move a certificate to the rejected store.
|
|
2161
2173
|
* If the certificate was previously trusted, it will be removed from the trusted folder.
|
|
2162
|
-
* @param
|
|
2174
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
2163
2175
|
*/
|
|
2164
|
-
async rejectCertificate(
|
|
2165
|
-
await this.#moveCertificate(
|
|
2176
|
+
async rejectCertificate(certificateOrChain) {
|
|
2177
|
+
await this.#moveCertificate(certificateOrChain, "rejected");
|
|
2166
2178
|
}
|
|
2167
2179
|
/**
|
|
2168
2180
|
* Move a certificate to the trusted store.
|
|
2169
2181
|
* If the certificate was previously rejected, it will be removed from the rejected folder.
|
|
2170
|
-
* @param
|
|
2182
|
+
* @param certificateOrChain - the DER-encoded certificate or certificate chain
|
|
2171
2183
|
*/
|
|
2172
|
-
async trustCertificate(
|
|
2173
|
-
await this.#moveCertificate(
|
|
2184
|
+
async trustCertificate(certificateOrChain) {
|
|
2185
|
+
await this.#moveCertificate(certificateOrChain, "trusted");
|
|
2174
2186
|
}
|
|
2175
2187
|
/**
|
|
2176
2188
|
* Check whether the trusted certificate store is empty.
|
|
@@ -2224,37 +2236,46 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2224
2236
|
* @returns `"Good"` if trusted, `"BadCertificateUntrusted"` if rejected/unknown,
|
|
2225
2237
|
* or `"BadCertificateInvalid"` if the certificate cannot be parsed.
|
|
2226
2238
|
*/
|
|
2227
|
-
async isCertificateTrusted(
|
|
2228
|
-
let fingerprint;
|
|
2239
|
+
async isCertificateTrusted(certificateOrCertificateChain) {
|
|
2229
2240
|
try {
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
if (this.#thumbs.trusted.has(fingerprint)) {
|
|
2235
|
-
return "Good";
|
|
2236
|
-
}
|
|
2237
|
-
if (!this.#thumbs.rejected.has(fingerprint)) {
|
|
2238
|
-
if (!this.untrustUnknownCertificate) {
|
|
2239
|
-
return "Good";
|
|
2241
|
+
const chain = coerceCertificateChain(certificateOrCertificateChain);
|
|
2242
|
+
const leafCertificate = chain[0];
|
|
2243
|
+
if (chain.length < 1) {
|
|
2244
|
+
return "BadCertificateInvalid";
|
|
2240
2245
|
}
|
|
2246
|
+
let fingerprint;
|
|
2241
2247
|
try {
|
|
2242
|
-
|
|
2248
|
+
fingerprint = makeFingerprint(chain[0]);
|
|
2243
2249
|
} catch (_err) {
|
|
2244
2250
|
return "BadCertificateInvalid";
|
|
2245
2251
|
}
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
this.#thumbs.rejected.
|
|
2252
|
+
if (this.#thumbs.trusted.has(fingerprint)) {
|
|
2253
|
+
return "Good";
|
|
2254
|
+
}
|
|
2255
|
+
if (!this.#thumbs.rejected.has(fingerprint)) {
|
|
2256
|
+
if (!this.untrustUnknownCertificate) {
|
|
2257
|
+
return "Good";
|
|
2258
|
+
}
|
|
2259
|
+
try {
|
|
2260
|
+
exploreCertificateInfo(chain[0]);
|
|
2261
|
+
} catch (_err) {
|
|
2262
|
+
return "BadCertificateInvalid";
|
|
2263
|
+
}
|
|
2264
|
+
const filename = path6.join(this.rejectedFolder, `${buildIdealCertificateName(leafCertificate)}.pem`);
|
|
2265
|
+
debugLog("certificate has never been seen before and is now rejected (untrusted) ", filename);
|
|
2266
|
+
await fsWriteFile(filename, toPem2(chain, "CERTIFICATE"));
|
|
2267
|
+
this.#thumbs.rejected.set(fingerprint, { certificate: leafCertificate, filename });
|
|
2268
|
+
}
|
|
2269
|
+
return "BadCertificateUntrusted";
|
|
2270
|
+
} catch (_err) {
|
|
2271
|
+
return "BadCertificateInvalid";
|
|
2250
2272
|
}
|
|
2251
|
-
return "BadCertificateUntrusted";
|
|
2252
2273
|
}
|
|
2253
2274
|
async #innerVerifyCertificateAsync(certificateOrChain, _isIssuer, level, options) {
|
|
2254
2275
|
if (level >= 5) {
|
|
2255
2276
|
return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
|
|
2256
2277
|
}
|
|
2257
|
-
const chain =
|
|
2278
|
+
const chain = coerceCertificateChain(certificateOrChain);
|
|
2258
2279
|
debugLog("NB CERTIFICATE IN CHAIN = ", chain.length);
|
|
2259
2280
|
const info = exploreCertificate2(chain[0]);
|
|
2260
2281
|
let hasValidIssuer = false;
|
|
@@ -2309,7 +2330,7 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2309
2330
|
return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
|
|
2310
2331
|
}
|
|
2311
2332
|
hasValidIssuer = true;
|
|
2312
|
-
let revokedStatus = await this.isCertificateRevoked(
|
|
2333
|
+
let revokedStatus = await this.isCertificateRevoked(chain, issuerCertificate);
|
|
2313
2334
|
if (revokedStatus === "BadCertificateRevocationUnknown" /* BadCertificateRevocationUnknown */) {
|
|
2314
2335
|
if (options?.ignoreMissingRevocationList) {
|
|
2315
2336
|
revokedStatus = "Good" /* Good */;
|
|
@@ -2334,11 +2355,11 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2334
2355
|
debugLog("Self-signed Certificate signature is not valid");
|
|
2335
2356
|
return "BadSecurityChecksFailed" /* BadSecurityChecksFailed */;
|
|
2336
2357
|
}
|
|
2337
|
-
const revokedStatus = await this.isCertificateRevoked(
|
|
2358
|
+
const revokedStatus = await this.isCertificateRevoked(chain);
|
|
2338
2359
|
debugLog("revokedStatus of self signed certificate:", revokedStatus);
|
|
2339
2360
|
}
|
|
2340
2361
|
}
|
|
2341
|
-
const status = await this.#checkRejectedOrTrusted(
|
|
2362
|
+
const status = await this.#checkRejectedOrTrusted(chain[0]);
|
|
2342
2363
|
if (status === "rejected") {
|
|
2343
2364
|
if (!(options.acceptCertificateWithValidIssuerChain && hasValidIssuer && hasTrustedIssuer)) {
|
|
2344
2365
|
return "BadCertificateUntrusted" /* BadCertificateUntrusted */;
|
|
@@ -2396,17 +2417,15 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2396
2417
|
* @returns the verification status code
|
|
2397
2418
|
*/
|
|
2398
2419
|
async verifyCertificateAsync(certificate, options) {
|
|
2399
|
-
|
|
2420
|
+
const chain = coerceCertificateChain(certificate);
|
|
2421
|
+
for (const element of chain) {
|
|
2400
2422
|
try {
|
|
2401
|
-
|
|
2402
|
-
for (const element of derElements) {
|
|
2403
|
-
exploreCertificateInfo(element);
|
|
2404
|
-
}
|
|
2423
|
+
exploreCertificateInfo(element);
|
|
2405
2424
|
} catch (_err) {
|
|
2406
2425
|
return "BadCertificateInvalid" /* BadCertificateInvalid */;
|
|
2407
2426
|
}
|
|
2408
2427
|
}
|
|
2409
|
-
const status1 = await this.#innerVerifyCertificateAsync(
|
|
2428
|
+
const status1 = await this.#innerVerifyCertificateAsync(chain, false, 0, options);
|
|
2410
2429
|
return status1;
|
|
2411
2430
|
}
|
|
2412
2431
|
/**
|
|
@@ -2836,7 +2855,7 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2836
2855
|
async #addTrustedCertificateFromChainImpl(certificateChain) {
|
|
2837
2856
|
let certificates;
|
|
2838
2857
|
try {
|
|
2839
|
-
certificates =
|
|
2858
|
+
certificates = coerceCertificateChain(certificateChain);
|
|
2840
2859
|
} catch (_err) {
|
|
2841
2860
|
return "BadCertificateInvalid" /* BadCertificateInvalid */;
|
|
2842
2861
|
}
|
|
@@ -2920,7 +2939,7 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2920
2939
|
return "BadCertificateInvalid" /* BadCertificateInvalid */;
|
|
2921
2940
|
}
|
|
2922
2941
|
}
|
|
2923
|
-
await this.trustCertificate(
|
|
2942
|
+
await this.trustCertificate(certificates);
|
|
2924
2943
|
return "Good" /* Good */;
|
|
2925
2944
|
}
|
|
2926
2945
|
/**
|
|
@@ -2963,7 +2982,7 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
2963
2982
|
*
|
|
2964
2983
|
*/
|
|
2965
2984
|
async findIssuerCertificate(certificate) {
|
|
2966
|
-
const firstCertificate =
|
|
2985
|
+
const firstCertificate = coerceCertificateChain(certificate)[0];
|
|
2967
2986
|
const certInfo = exploreCertificate2(firstCertificate);
|
|
2968
2987
|
if (isSelfSigned2(certInfo)) {
|
|
2969
2988
|
return firstCertificate;
|
|
@@ -3000,7 +3019,7 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
3000
3019
|
* @private
|
|
3001
3020
|
*/
|
|
3002
3021
|
async #checkRejectedOrTrusted(certificate) {
|
|
3003
|
-
const firstCertificate =
|
|
3022
|
+
const firstCertificate = coerceCertificateChain(certificate)[0];
|
|
3004
3023
|
const fingerprint = makeFingerprint(firstCertificate);
|
|
3005
3024
|
debugLog("#checkRejectedOrTrusted fingerprint ", short(fingerprint));
|
|
3006
3025
|
await this.#readCertificates();
|
|
@@ -3012,12 +3031,14 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
3012
3031
|
}
|
|
3013
3032
|
return "unknown";
|
|
3014
3033
|
}
|
|
3015
|
-
async #moveCertificate(
|
|
3034
|
+
async #moveCertificate(certificateOrChain, newStatus) {
|
|
3016
3035
|
await this.withLock2(async () => {
|
|
3036
|
+
const chain = coerceCertificateChain(certificateOrChain);
|
|
3037
|
+
const certificate = chain[0];
|
|
3017
3038
|
const fingerprint = makeFingerprint(certificate);
|
|
3018
3039
|
let status = await this.#checkRejectedOrTrusted(certificate);
|
|
3019
3040
|
if (status === "unknown") {
|
|
3020
|
-
const pem = toPem2(
|
|
3041
|
+
const pem = toPem2(chain, "CERTIFICATE");
|
|
3021
3042
|
const filename = path6.join(this.rejectedFolder, `${buildIdealCertificateName(certificate)}.pem`);
|
|
3022
3043
|
await fs10.promises.writeFile(filename, pem);
|
|
3023
3044
|
this.#thumbs.rejected.set(fingerprint, { certificate, filename });
|
|
@@ -3067,13 +3088,17 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
3067
3088
|
* found.
|
|
3068
3089
|
*/
|
|
3069
3090
|
async isCertificateRevoked(certificate, issuerCertificate) {
|
|
3070
|
-
const
|
|
3091
|
+
const chain = coerceCertificateChain(certificate);
|
|
3092
|
+
const firstCertificate = chain[0];
|
|
3071
3093
|
if (isSelfSigned3(firstCertificate)) {
|
|
3072
3094
|
return "Good" /* Good */;
|
|
3073
3095
|
}
|
|
3074
3096
|
if (!issuerCertificate) {
|
|
3075
3097
|
issuerCertificate = await this.findIssuerCertificate(firstCertificate);
|
|
3076
3098
|
}
|
|
3099
|
+
if (!issuerCertificate) {
|
|
3100
|
+
issuerCertificate = findIssuerCertificateInChain(firstCertificate, chain);
|
|
3101
|
+
}
|
|
3077
3102
|
if (!issuerCertificate) {
|
|
3078
3103
|
return "BadCertificateChainIncomplete" /* BadCertificateChainIncomplete */;
|
|
3079
3104
|
}
|
|
@@ -3200,7 +3225,25 @@ var CertificateManager = class _CertificateManager extends EventEmitter {
|
|
|
3200
3225
|
try {
|
|
3201
3226
|
const stat = await fs10.promises.stat(filename);
|
|
3202
3227
|
if (!stat.isFile()) continue;
|
|
3203
|
-
const
|
|
3228
|
+
const certs = await readCertificateChainAsync(filename);
|
|
3229
|
+
if (certs.length === 0) continue;
|
|
3230
|
+
const certificate = certs[0];
|
|
3231
|
+
if (certs.length > 1) {
|
|
3232
|
+
try {
|
|
3233
|
+
await fs10.promises.writeFile(filename, toPem2(certs, "CERTIFICATE"), "ascii");
|
|
3234
|
+
} catch (writeErr) {
|
|
3235
|
+
debugLog(`scanCertFolder: could not rewrite legacy PEM ${filename} (read-only fs?)`, writeErr);
|
|
3236
|
+
}
|
|
3237
|
+
for (let i = 1; i < certs.length; i++) {
|
|
3238
|
+
if (isIssuer(certs[i])) {
|
|
3239
|
+
try {
|
|
3240
|
+
await this.addIssuer(certs[i]);
|
|
3241
|
+
} catch (issuerErr) {
|
|
3242
|
+
debugLog(`scanCertFolder: could not auto-register issuer from ${filename}`, issuerErr);
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3204
3247
|
const info = exploreCertificate2(certificate);
|
|
3205
3248
|
const fingerprint = makeFingerprint(certificate);
|
|
3206
3249
|
index.set(fingerprint, { certificate, filename, info });
|
|
@@ -3352,6 +3395,7 @@ export {
|
|
|
3352
3395
|
VerificationStatus,
|
|
3353
3396
|
adjustApplicationUri,
|
|
3354
3397
|
adjustDate,
|
|
3398
|
+
coerceCertificateChain,
|
|
3355
3399
|
convertPFXtoPEM,
|
|
3356
3400
|
createPFX,
|
|
3357
3401
|
dumpPFX,
|