node-opcua-pki 5.5.0 → 5.7.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/bin/crypto_create_CA.cjs +35 -35
- package/dist/test/helpers.d.ts +6 -0
- package/dist/test/helpers.js +60 -0
- package/dist/test/test_advanced_certificate_validation.d.ts +1 -0
- package/dist/test/test_advanced_certificate_validation.js +95 -0
- package/dist/test/test_certificate_authority.d.ts +1 -0
- package/dist/test/test_certificate_authority.js +261 -0
- package/dist/test/test_certificate_manager.d.ts +1 -0
- package/dist/test/test_certificate_manager.js +239 -0
- package/dist/test/test_certificate_validation.d.ts +1 -0
- package/dist/test/test_certificate_validation.js +160 -0
- package/dist/test/test_concurrency.d.ts +1 -0
- package/dist/test/test_concurrency.js +53 -0
- package/dist/test/test_create_signing_request.d.ts +1 -0
- package/dist/test/test_create_signing_request.js +104 -0
- package/dist/test/test_crypto_create_CA.d.ts +1 -0
- package/dist/test/test_crypto_create_CA.js +251 -0
- package/dist/test/test_ctt_use_cases.d.ts +1 -0
- package/dist/test/test_ctt_use_cases.js +391 -0
- package/dist/test/test_install_prerequisite.d.ts +1 -0
- package/dist/test/test_install_prerequisite.js +18 -0
- package/dist/test/test_toolbox.d.ts +1 -0
- package/dist/test/test_toolbox.js +56 -0
- package/package.json +8 -37
- package/CHANGELOG.md +0 -1139
- package/bin/install_prerequisite.cjs +0 -9
package/bin/crypto_create_CA.cjs
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
3
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
-
// node-opcua-pki
|
|
5
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
6
|
-
// Copyright (c) 2014-2020 - Etienne Rossignon - etienne.rossignon (at) gadz.org
|
|
7
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
8
|
-
//
|
|
9
|
-
// This project is licensed under the terms of the MIT license.
|
|
10
|
-
//
|
|
11
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
12
|
-
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
13
|
-
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
14
|
-
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
15
|
-
//
|
|
16
|
-
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
17
|
-
// Software.
|
|
18
|
-
//
|
|
19
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
20
|
-
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
21
|
-
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
22
|
-
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
24
|
-
"use strict";
|
|
25
|
-
|
|
26
|
-
// note: we remove use of update-notifier as it is ESM now and
|
|
27
|
-
// old version have reported vulnerabilities
|
|
28
|
-
//xx const updateNotifier = require("update-notifier");
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
30
|
-
const _pkg = require("../package.json");
|
|
31
|
-
|
|
32
|
-
// eslint-disable-next-line no-undef
|
|
33
|
-
const { main } = require("../dist/lib/ca/crypto_create_CA.js");
|
|
34
|
-
|
|
35
|
-
main(process.argv.splice(2));
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
3
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
// node-opcua-pki
|
|
5
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
// Copyright (c) 2014-2020 - Etienne Rossignon - etienne.rossignon (at) gadz.org
|
|
7
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
//
|
|
9
|
+
// This project is licensed under the terms of the MIT license.
|
|
10
|
+
//
|
|
11
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
12
|
+
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
13
|
+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
14
|
+
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
15
|
+
//
|
|
16
|
+
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
17
|
+
// Software.
|
|
18
|
+
//
|
|
19
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
20
|
+
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
21
|
+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
22
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
24
|
+
"use strict";
|
|
25
|
+
|
|
26
|
+
// note: we remove use of update-notifier as it is ESM now and
|
|
27
|
+
// old version have reported vulnerabilities
|
|
28
|
+
//xx const updateNotifier = require("update-notifier");
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
30
|
+
const _pkg = require("../package.json");
|
|
31
|
+
|
|
32
|
+
// eslint-disable-next-line no-undef
|
|
33
|
+
const { main } = require("../dist/lib/ca/crypto_create_CA.js");
|
|
34
|
+
|
|
35
|
+
main(process.argv.splice(2));
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.grep = grep;
|
|
16
|
+
exports.beforeTest = beforeTest;
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const rimraf_1 = __importDefault(require("rimraf"));
|
|
19
|
+
const index_1 = require("../lib/index");
|
|
20
|
+
const tmpFolder = path_1.default.join(__dirname, "../tmp");
|
|
21
|
+
index_1.g_config.silent = !process.env.VERBOSE;
|
|
22
|
+
function grep(data, regExp) {
|
|
23
|
+
return data
|
|
24
|
+
.split("\n")
|
|
25
|
+
.filter((l) => l.match(regExp))
|
|
26
|
+
.join("\n");
|
|
27
|
+
}
|
|
28
|
+
let doneOnce = false;
|
|
29
|
+
function beforeTest(self, nextFunction) {
|
|
30
|
+
self.timeout("5 minutes");
|
|
31
|
+
const testData = {
|
|
32
|
+
tmpFolder,
|
|
33
|
+
};
|
|
34
|
+
before(() => __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
if (process.env.PKITEST === "NOCLEAN") {
|
|
36
|
+
doneOnce = true;
|
|
37
|
+
}
|
|
38
|
+
// tslint:disable-next-line: no-console
|
|
39
|
+
function next() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
if (nextFunction) {
|
|
42
|
+
yield nextFunction();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
testData.tmpFolder = tmpFolder;
|
|
47
|
+
if (!doneOnce) {
|
|
48
|
+
doneOnce = true;
|
|
49
|
+
// tslint:disable-next-line: no-console
|
|
50
|
+
(0, index_1.warningLog)(" .... cleaning temporary folders ...", tmpFolder);
|
|
51
|
+
yield (0, rimraf_1.default)(tmpFolder);
|
|
52
|
+
(0, index_1.warningLog)(" ..... folder cleaned");
|
|
53
|
+
(0, index_1.mkdirRecursiveSync)(tmpFolder);
|
|
54
|
+
(0, index_1.warningLog)(" ..... creating empty folder", tmpFolder);
|
|
55
|
+
}
|
|
56
|
+
yield next();
|
|
57
|
+
}));
|
|
58
|
+
return testData;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "should";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const sinon_1 = __importDefault(require("sinon"));
|
|
18
|
+
require("should");
|
|
19
|
+
const lib_1 = require("../lib");
|
|
20
|
+
const helpers_1 = require("./helpers");
|
|
21
|
+
const node_opcua_crypto_1 = require("node-opcua-crypto");
|
|
22
|
+
describe("Check Validate Certificate", function () {
|
|
23
|
+
const testData = (0, helpers_1.beforeTest)(this);
|
|
24
|
+
let clock;
|
|
25
|
+
before(() => {
|
|
26
|
+
clock = sinon_1.default.useFakeTimers({
|
|
27
|
+
shouldAdvanceTime: true,
|
|
28
|
+
now: new Date(2020, 1, 12).getTime(),
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
after(() => {
|
|
32
|
+
clock.restore();
|
|
33
|
+
});
|
|
34
|
+
it("should verifyCertificateAsync", () => __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
const options = {
|
|
36
|
+
location: path_1.default.join(testData.tmpFolder, "PKI"),
|
|
37
|
+
};
|
|
38
|
+
const certificateManager = new lib_1.CertificateManager(options);
|
|
39
|
+
yield certificateManager.initialize();
|
|
40
|
+
const caCertificateFilename = path_1.default.join(__dirname, "fixtures/CTT_sample_certificates/CA/certs/ctt_ca1I.der");
|
|
41
|
+
const crlFilename = path_1.default.join(__dirname, "fixtures/CTT_sample_certificates/CA/crl/ctt_ca1I.crl");
|
|
42
|
+
const cert1Filename = path_1.default.join(__dirname, "fixtures/CTT_sample_certificates/CA/certs/ctt_ca1I_appT.der");
|
|
43
|
+
const cert2Filename = path_1.default.join(__dirname, "fixtures/CTT_sample_certificates/CA/certs/ctt_ca1I_appTR.der");
|
|
44
|
+
// installing the CA certificate
|
|
45
|
+
const caCert = (0, node_opcua_crypto_1.readCertificate)(caCertificateFilename);
|
|
46
|
+
let caCertStatus = yield certificateManager.verifyCertificate(caCert);
|
|
47
|
+
caCertStatus.should.eql("BadCertificateUntrusted");
|
|
48
|
+
// installing the 1st cer
|
|
49
|
+
const cert1 = fs_1.default.readFileSync(cert1Filename);
|
|
50
|
+
const cert2 = fs_1.default.readFileSync(cert2Filename);
|
|
51
|
+
yield certificateManager.trustCertificate(cert1);
|
|
52
|
+
yield certificateManager.trustCertificate(cert2);
|
|
53
|
+
{
|
|
54
|
+
const cert1Status = yield certificateManager.verifyCertificate(cert1);
|
|
55
|
+
// should be -BadCertificateChainIncomplete because the issuer cert is not in the issuer list
|
|
56
|
+
cert1Status.should.eql("BadCertificateChainIncomplete");
|
|
57
|
+
}
|
|
58
|
+
// installing the 2nd cert
|
|
59
|
+
{
|
|
60
|
+
const cert2Status = yield certificateManager.verifyCertificate(cert2);
|
|
61
|
+
// should be -BadCertificateChainIncomplete because the issuer cert is not in the issuer list
|
|
62
|
+
cert2Status.should.eql("BadCertificateChainIncomplete");
|
|
63
|
+
}
|
|
64
|
+
// now move the caCert to the issue list
|
|
65
|
+
const status = yield certificateManager.addIssuer(caCert, true);
|
|
66
|
+
status.should.eql("Good");
|
|
67
|
+
caCertStatus = yield certificateManager.verifyCertificate(caCert);
|
|
68
|
+
caCertStatus.should.eql("BadCertificateUntrusted");
|
|
69
|
+
{
|
|
70
|
+
const cert1Status = yield certificateManager.verifyCertificate(cert1);
|
|
71
|
+
cert1Status.should.eql("BadCertificateRevocationUnknown");
|
|
72
|
+
const cert1Status1 = yield certificateManager.verifyCertificate(cert1, {});
|
|
73
|
+
cert1Status1.should.eql("BadCertificateRevocationUnknown");
|
|
74
|
+
const cert1Status2 = yield certificateManager.verifyCertificate(cert1, { ignoreMissingRevocationList: true });
|
|
75
|
+
cert1Status2.should.eql("Good");
|
|
76
|
+
}
|
|
77
|
+
//
|
|
78
|
+
{
|
|
79
|
+
const certEStatus = yield certificateManager.verifyCertificate(cert2);
|
|
80
|
+
certEStatus.should.eql("BadCertificateRevocationUnknown");
|
|
81
|
+
}
|
|
82
|
+
// now move the crl to the crl list
|
|
83
|
+
const crl = fs_1.default.readFileSync(crlFilename);
|
|
84
|
+
yield certificateManager.addRevocationList(crl);
|
|
85
|
+
{
|
|
86
|
+
const cert1Status = yield certificateManager.verifyCertificate(cert1);
|
|
87
|
+
cert1Status.should.eql("Good");
|
|
88
|
+
}
|
|
89
|
+
{
|
|
90
|
+
const cert2Status = yield certificateManager.verifyCertificate(cert2);
|
|
91
|
+
cert2Status.should.eql("BadCertificateRevoked");
|
|
92
|
+
}
|
|
93
|
+
}));
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=test_advanced_certificate_validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// tslint:disable:no-console
|
|
3
|
+
// tslint:disable:no-shadowed-variable
|
|
4
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
7
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
8
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const node_opcua_crypto_1 = require("node-opcua-crypto");
|
|
20
|
+
const index_1 = require("../lib/index");
|
|
21
|
+
const with_openssl_1 = require("../lib/toolbox/with_openssl");
|
|
22
|
+
const certificate_authority_1 = require("../lib/ca/certificate_authority");
|
|
23
|
+
const helpers_1 = require("./helpers");
|
|
24
|
+
const doDebug = !!process.env.DEBUG;
|
|
25
|
+
describe("Certificate Authority", function () {
|
|
26
|
+
const testData = (0, helpers_1.beforeTest)(this);
|
|
27
|
+
let options = {};
|
|
28
|
+
before(() => {
|
|
29
|
+
options = {
|
|
30
|
+
keySize: 2048,
|
|
31
|
+
location: path_1.default.join(testData.tmpFolder, "CA"),
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
it("should read openssl version", () => __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
let output = yield (0, with_openssl_1.execute_openssl)("version", { cwd: "." });
|
|
36
|
+
output = output.trim();
|
|
37
|
+
index_1.g_config.opensslVersion.should.eql(output);
|
|
38
|
+
}));
|
|
39
|
+
it("should create a CertificateAuthority", () => __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
const ca = new certificate_authority_1.CertificateAuthority(options);
|
|
41
|
+
yield ca.initialize();
|
|
42
|
+
}));
|
|
43
|
+
});
|
|
44
|
+
describe("Signing Certificate with Certificate Authority", function () {
|
|
45
|
+
const testData = (0, helpers_1.beforeTest)(this);
|
|
46
|
+
let theCertificateAuthority;
|
|
47
|
+
let someCertificateManager;
|
|
48
|
+
before(() => __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
theCertificateAuthority = new certificate_authority_1.CertificateAuthority({
|
|
50
|
+
keySize: 2048,
|
|
51
|
+
location: path_1.default.join(testData.tmpFolder, "CA"),
|
|
52
|
+
});
|
|
53
|
+
someCertificateManager = new index_1.CertificateManager({
|
|
54
|
+
location: path_1.default.join(testData.tmpFolder, "PI"),
|
|
55
|
+
});
|
|
56
|
+
yield someCertificateManager.initialize();
|
|
57
|
+
yield theCertificateAuthority.initialize();
|
|
58
|
+
yield someCertificateManager.dispose();
|
|
59
|
+
}));
|
|
60
|
+
function createCertificateRequest() {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
// let create a certificate request from the certificate manager
|
|
63
|
+
const params = {
|
|
64
|
+
applicationUri: "MY:APPLICATION:URI",
|
|
65
|
+
dns: ["localhost", "my.domain.com"],
|
|
66
|
+
ip: ["192.123.145.121"],
|
|
67
|
+
subject: "/CN=MyCommonName",
|
|
68
|
+
// can only be TODAY due to openssl limitation : startDate: new Date(2010,2,2),
|
|
69
|
+
validity: 365 * 7,
|
|
70
|
+
};
|
|
71
|
+
const certificateSigningRequestFilename = yield someCertificateManager.createCertificateRequest(params);
|
|
72
|
+
return certificateSigningRequestFilename;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function verifyCertificateAgainstPrivateKey(certificate) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
console.log("someCertificateManager.privateKey=", someCertificateManager.privateKey);
|
|
78
|
+
const privateKey = (0, node_opcua_crypto_1.readPrivateKey)(someCertificateManager.privateKey);
|
|
79
|
+
const rsaLength = (0, node_opcua_crypto_1.rsaLengthPrivateKey)(privateKey);
|
|
80
|
+
if (!(0, node_opcua_crypto_1.certificateMatchesPrivateKey)(certificate, privateKey)) {
|
|
81
|
+
throw new Error("Certificate and private key do not match !!!");
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
it("T0 - should have a CA Certificate", () => __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
fs_1.default.existsSync(theCertificateAuthority.caCertificate).should.eql(true);
|
|
87
|
+
}));
|
|
88
|
+
it("T1 - should have a CA Certificate with a CRL", () => __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
yield theCertificateAuthority.constructCACertificateWithCRL();
|
|
90
|
+
fs_1.default.existsSync(theCertificateAuthority.caCertificateWithCrl).should.eql(true);
|
|
91
|
+
}));
|
|
92
|
+
it("T2 - should sign a Certificate Request", () => __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const self = {
|
|
94
|
+
certificateRequest: "",
|
|
95
|
+
};
|
|
96
|
+
// create a Certificate Signing Request
|
|
97
|
+
self.certificateRequest = yield createCertificateRequest();
|
|
98
|
+
fs_1.default.existsSync(self.certificateRequest).should.eql(true);
|
|
99
|
+
const certificateFilename = path_1.default.join(testData.tmpFolder, "sample_certificate.pem");
|
|
100
|
+
const params = {
|
|
101
|
+
applicationUri: "BAD SHOULD BE IN REQUEST",
|
|
102
|
+
startDate: new Date(2011, 25, 12),
|
|
103
|
+
validity: 10 * 365,
|
|
104
|
+
};
|
|
105
|
+
yield theCertificateAuthority.signCertificateRequest(certificateFilename, self.certificateRequest, params);
|
|
106
|
+
fs_1.default.existsSync(certificateFilename).should.eql(true, "certificate file " + certificateFilename + " must exist");
|
|
107
|
+
// Serial Number: 4096 (0x1000)
|
|
108
|
+
const certificateChain = (0, node_opcua_crypto_1.readCertificate)(certificateFilename);
|
|
109
|
+
const elements = (0, node_opcua_crypto_1.split_der)(certificateChain);
|
|
110
|
+
elements.length.should.eql(2);
|
|
111
|
+
// should have 2 x -----BEGIN CERTIFICATE----- in the chain
|
|
112
|
+
// should verify that certificate is valid
|
|
113
|
+
// verify the subject Alternative Name
|
|
114
|
+
const csr = (0, node_opcua_crypto_1.readCertificate)(self.certificateRequest);
|
|
115
|
+
const infoCSR = (0, node_opcua_crypto_1.exploreCertificateSigningRequest)(csr);
|
|
116
|
+
const info = (0, node_opcua_crypto_1.exploreCertificate)(certificateChain);
|
|
117
|
+
if (doDebug) {
|
|
118
|
+
console.log(infoCSR.extensionRequest.basicConstraints);
|
|
119
|
+
console.log(info.tbsCertificate.extensions.basicConstraints);
|
|
120
|
+
console.log(infoCSR.extensionRequest.keyUsage);
|
|
121
|
+
console.log(info.tbsCertificate.extensions.keyUsage);
|
|
122
|
+
console.log(infoCSR.extensionRequest.subjectAltName);
|
|
123
|
+
console.log(info.tbsCertificate.extensions.subjectAltName);
|
|
124
|
+
}
|
|
125
|
+
infoCSR.extensionRequest.subjectAltName.should.eql(info.tbsCertificate.extensions.subjectAltName);
|
|
126
|
+
// todo
|
|
127
|
+
yield verifyCertificateAgainstPrivateKey(elements[0]);
|
|
128
|
+
}));
|
|
129
|
+
function sign(certificateRequest, startDate, validity) {
|
|
130
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
const a = (0, with_openssl_1.x509Date)(startDate) + "_" + validity;
|
|
132
|
+
fs_1.default.existsSync(certificateRequest).should.eql(true, "certificate request " + certificateRequest + " must exist");
|
|
133
|
+
const certificateFilename = path_1.default.join(testData.tmpFolder, "sample_certificate" + a + ".pem");
|
|
134
|
+
const params = {
|
|
135
|
+
applicationUri: "BAD SHOULD BE IN REQUEST",
|
|
136
|
+
startDate,
|
|
137
|
+
validity,
|
|
138
|
+
};
|
|
139
|
+
if (fs_1.default.existsSync(certificateFilename)) {
|
|
140
|
+
fs_1.default.unlinkSync(certificateFilename);
|
|
141
|
+
}
|
|
142
|
+
const certificate = yield theCertificateAuthority.signCertificateRequest(certificateFilename, certificateRequest, params);
|
|
143
|
+
fs_1.default.existsSync(certificate).should.eql(true, "certificate: " + certificateFilename + " should exists");
|
|
144
|
+
// Serial Number: 4096 (0x1000)
|
|
145
|
+
// should have 2 x -----BEGIN CERTIFICATE----- in the chain
|
|
146
|
+
return certificate;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const now = new Date();
|
|
150
|
+
const lastYear = new Date();
|
|
151
|
+
lastYear.setFullYear(now.getFullYear() - 1);
|
|
152
|
+
const nextYear = new Date();
|
|
153
|
+
nextYear.setFullYear(now.getFullYear() + 1);
|
|
154
|
+
it("T3 - should create various Certificates signed by the CA authority", () => __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
// create a Certificate Signing Request
|
|
156
|
+
const certificateRequest = yield createCertificateRequest();
|
|
157
|
+
fs_1.default.existsSync(certificateRequest).should.eql(true, "certificate request " + certificateRequest + " must exist");
|
|
158
|
+
yield sign(certificateRequest, lastYear, 200);
|
|
159
|
+
yield sign(certificateRequest, lastYear, 10 * 365); // valid
|
|
160
|
+
yield sign(certificateRequest, nextYear, 365); // not started yet
|
|
161
|
+
}));
|
|
162
|
+
it("T4 - should create various self-signed Certificates using the CA", () => __awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
// using a CA to construct self-signed certificates provides the following benefits:
|
|
164
|
+
// - startDate can be easily specified in the past or the future
|
|
165
|
+
// - certificate can be revoked ??? to be checked.
|
|
166
|
+
const privateKey = someCertificateManager.privateKey;
|
|
167
|
+
const certificate = path_1.default.join(testData.tmpFolder, "sample_self_signed_certificate.pem");
|
|
168
|
+
fs_1.default.existsSync(certificate).should.eql(false, certificate + " must not exist");
|
|
169
|
+
yield theCertificateAuthority.createSelfSignedCertificate(certificate, privateKey, {
|
|
170
|
+
applicationUri: "SomeUri",
|
|
171
|
+
});
|
|
172
|
+
fs_1.default.existsSync(certificate).should.eql(true);
|
|
173
|
+
yield verifyCertificateAgainstPrivateKey((0, node_opcua_crypto_1.readCertificate)(certificate));
|
|
174
|
+
}));
|
|
175
|
+
/**
|
|
176
|
+
*
|
|
177
|
+
* @param certificate {String} certificate to create
|
|
178
|
+
*/
|
|
179
|
+
function createSelfSignedCertificate(certificate, privateKey) {
|
|
180
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
181
|
+
const startDate = new Date();
|
|
182
|
+
const validity = 1000;
|
|
183
|
+
const params = {
|
|
184
|
+
applicationUri: "BAD SHOULD BE IN REQUEST",
|
|
185
|
+
startDate,
|
|
186
|
+
validity,
|
|
187
|
+
};
|
|
188
|
+
yield theCertificateAuthority.createSelfSignedCertificate(certificate, privateKey, params);
|
|
189
|
+
// console.log("signed_certificate = signed_certificate", certificate);
|
|
190
|
+
return certificate;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
it("T5 - should revoke a self-signed certificate", () => __awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
const privateKey = someCertificateManager.privateKey;
|
|
195
|
+
const certificate = path_1.default.join(testData.tmpFolder, "certificate_to_be_revoked1.pem");
|
|
196
|
+
yield createSelfSignedCertificate(certificate, privateKey);
|
|
197
|
+
fs_1.default.existsSync(certificate).should.eql(true);
|
|
198
|
+
yield theCertificateAuthority.revokeCertificate(certificate, {});
|
|
199
|
+
}));
|
|
200
|
+
function createCertificateFromCA() {
|
|
201
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
const certificateRequest = yield createCertificateRequest();
|
|
203
|
+
const signedCertificate = yield sign(certificateRequest, lastYear, 10 * 365 + 10);
|
|
204
|
+
return signedCertificate;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
it("T6 - should revoke a certificate emitted by the CA", () => __awaiter(this, void 0, void 0, function* () {
|
|
208
|
+
// g_config.silent = false;
|
|
209
|
+
const caCertificateFilename = theCertificateAuthority.caCertificate;
|
|
210
|
+
const caCRLFilename = theCertificateAuthority.revocationList;
|
|
211
|
+
const caCertificate = yield (0, node_opcua_crypto_1.readCertificate)(caCertificateFilename);
|
|
212
|
+
const caCRLBefore = yield (0, node_opcua_crypto_1.readCertificateRevocationList)(caCRLFilename);
|
|
213
|
+
const certificateFilename = yield createCertificateFromCA();
|
|
214
|
+
fs_1.default.existsSync(certificateFilename).should.eql(true);
|
|
215
|
+
const certificate = yield (0, node_opcua_crypto_1.readCertificate)(certificateFilename);
|
|
216
|
+
// ---- lets create a
|
|
217
|
+
const pkiLocation = path_1.default.join(testData.tmpFolder, "somePKI");
|
|
218
|
+
const cm = new index_1.CertificateManager({
|
|
219
|
+
location: pkiLocation,
|
|
220
|
+
});
|
|
221
|
+
yield cm.initialize();
|
|
222
|
+
const status1 = yield cm.addIssuer(caCertificate, true, true);
|
|
223
|
+
status1.should.eql(index_1.VerificationStatus.Good);
|
|
224
|
+
const status4 = yield cm.addRevocationList(caCRLBefore);
|
|
225
|
+
status4.should.eql(index_1.VerificationStatus.Good);
|
|
226
|
+
// check status before revocation...
|
|
227
|
+
const validate1 = yield cm.verifyCertificate(certificate);
|
|
228
|
+
validate1.should.eql(index_1.VerificationStatus.Good);
|
|
229
|
+
// now revoke certificate
|
|
230
|
+
yield theCertificateAuthority.revokeCertificate(certificateFilename, {});
|
|
231
|
+
const caCRLAfter = yield (0, node_opcua_crypto_1.readCertificateRevocationList)(caCRLFilename);
|
|
232
|
+
const status3 = yield cm.addRevocationList(caCRLAfter);
|
|
233
|
+
status3.should.eql(index_1.VerificationStatus.Good);
|
|
234
|
+
const validate2 = yield cm.verifyCertificate(certificate);
|
|
235
|
+
validate2.should.eql(index_1.VerificationStatus.BadCertificateRevoked);
|
|
236
|
+
yield cm.dispose();
|
|
237
|
+
}));
|
|
238
|
+
it("T7 - it should automatically accept Certificate issued by a trusted issuer that is not in the CRL", () => __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
const caCertificateFilename = theCertificateAuthority.caCertificate;
|
|
240
|
+
const caCRLFilename = theCertificateAuthority.revocationList;
|
|
241
|
+
const caCertificate = yield (0, node_opcua_crypto_1.readCertificate)(caCertificateFilename);
|
|
242
|
+
const caCRLBefore = yield (0, node_opcua_crypto_1.readCertificateRevocationList)(caCRLFilename);
|
|
243
|
+
const certificateFilename = yield createCertificateFromCA();
|
|
244
|
+
fs_1.default.existsSync(certificateFilename).should.eql(true);
|
|
245
|
+
const certificate = yield (0, node_opcua_crypto_1.readCertificate)(certificateFilename);
|
|
246
|
+
// ---- lets create a
|
|
247
|
+
const pkiLocation = path_1.default.join(testData.tmpFolder, "somePKI1");
|
|
248
|
+
const cm = new index_1.CertificateManager({
|
|
249
|
+
location: pkiLocation,
|
|
250
|
+
});
|
|
251
|
+
yield cm.initialize();
|
|
252
|
+
const validate0 = yield cm.verifyCertificate(certificate);
|
|
253
|
+
validate0.should.eql(index_1.VerificationStatus.BadCertificateChainIncomplete);
|
|
254
|
+
const status1 = yield cm.addIssuer(caCertificate);
|
|
255
|
+
const status2 = yield cm.addRevocationList(caCRLBefore);
|
|
256
|
+
const validate1 = yield cm.verifyCertificate(certificate);
|
|
257
|
+
validate1.should.eql(index_1.VerificationStatus.BadCertificateUntrusted);
|
|
258
|
+
yield cm.dispose();
|
|
259
|
+
}));
|
|
260
|
+
});
|
|
261
|
+
//# sourceMappingURL=test_certificate_authority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "should";
|