node-opcua-pki 6.22.1 → 7.0.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/bin/install_prerequisite.ts +1 -1
- package/bin/pki.ts +1 -1
- package/bin/pki_config.example.js +0 -1
- package/dist/bin/install_prerequisite.d.ts +2 -0
- package/dist/bin/install_prerequisite.js +6 -0
- package/dist/bin/install_prerequisite.js.map +1 -0
- package/dist/bin/pki.d.ts +2 -0
- package/dist/bin/pki.js +4 -0
- package/dist/bin/pki.js.map +1 -0
- package/dist/lib/ca/backends/native_ca_backend.d.ts +49 -0
- package/dist/lib/ca/backends/native_ca_backend.js +365 -0
- package/dist/lib/ca/backends/native_ca_backend.js.map +1 -0
- package/dist/lib/ca/backends/openssl_ca_backend.d.ts +47 -0
- package/dist/lib/ca/backends/openssl_ca_backend.js +398 -0
- package/dist/lib/ca/backends/openssl_ca_backend.js.map +1 -0
- package/dist/lib/ca/certificate_authority.d.ts +62 -0
- package/dist/lib/ca/certificate_authority.js +91 -0
- package/dist/lib/ca/certificate_authority.js.map +1 -0
- package/dist/lib/ca/core/ca_backend.d.ts +89 -0
- package/dist/lib/ca/core/ca_backend.js +24 -0
- package/dist/lib/ca/core/ca_backend.js.map +1 -0
- package/dist/lib/ca/core/ca_database.d.ts +91 -0
- package/dist/lib/ca/core/ca_database.js +267 -0
- package/dist/lib/ca/core/ca_database.js.map +1 -0
- package/dist/{core-BwqSJPHc.d.mts → lib/ca/core/certificate_authority_core.d.ts} +45 -394
- package/dist/lib/ca/core/certificate_authority_core.js +1300 -0
- package/dist/lib/ca/core/certificate_authority_core.js.map +1 -0
- package/dist/lib/ca/core/index.d.ts +17 -0
- package/dist/lib/ca/core/index.js +25 -0
- package/dist/lib/ca/core/index.js.map +1 -0
- package/dist/lib/ca/crypto_create_CA.d.ts +1 -0
- package/dist/lib/ca/crypto_create_CA.js +821 -0
- package/dist/lib/ca/crypto_create_CA.js.map +1 -0
- package/dist/lib/ca/index.d.ts +1 -0
- package/dist/lib/ca/index.js +2 -0
- package/dist/lib/ca/index.js.map +1 -0
- package/dist/lib/ca/templates/ca_config_template.cnf.d.ts +2 -0
- package/dist/lib/ca/templates/ca_config_template.cnf.js +170 -0
- package/dist/lib/ca/templates/ca_config_template.cnf.js.map +1 -0
- package/dist/lib/core.d.ts +33 -0
- package/dist/lib/core.js +56 -0
- package/dist/lib/core.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.js +37 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/misc/applicationurn.d.ts +1 -0
- package/dist/lib/misc/applicationurn.js +40 -0
- package/dist/lib/misc/applicationurn.js.map +1 -0
- package/dist/lib/misc/hostname.d.ts +8 -0
- package/dist/lib/misc/hostname.js +82 -0
- package/dist/lib/misc/hostname.js.map +1 -0
- package/dist/lib/misc/subject.d.ts +2 -0
- package/dist/lib/misc/subject.js +2 -0
- package/dist/lib/misc/subject.js.map +1 -0
- package/dist/{index.d.ts → lib/pki/certificate_manager.d.ts} +24 -248
- package/dist/lib/pki/certificate_manager.js +2302 -0
- package/dist/lib/pki/certificate_manager.js.map +1 -0
- package/dist/lib/pki/templates/simple_config_template.cnf.d.ts +2 -0
- package/dist/lib/pki/templates/simple_config_template.cnf.js +74 -0
- package/dist/lib/pki/templates/simple_config_template.cnf.js.map +1 -0
- package/dist/lib/pki/toolbox_pfx.d.ts +127 -0
- package/dist/lib/pki/toolbox_pfx.js +248 -0
- package/dist/lib/pki/toolbox_pfx.js.map +1 -0
- package/dist/lib/toolbox/common.d.ts +150 -0
- package/dist/lib/toolbox/common.js +82 -0
- package/dist/lib/toolbox/common.js.map +1 -0
- package/dist/lib/toolbox/common2.d.ts +25 -0
- package/dist/lib/toolbox/common2.js +97 -0
- package/dist/lib/toolbox/common2.js.map +1 -0
- package/dist/lib/toolbox/config.d.ts +5 -0
- package/dist/lib/toolbox/config.js +28 -0
- package/dist/lib/toolbox/config.js.map +1 -0
- package/dist/lib/toolbox/debug.d.ts +5 -0
- package/dist/lib/toolbox/debug.js +35 -0
- package/dist/lib/toolbox/debug.js.map +1 -0
- package/dist/lib/toolbox/display.d.ts +4 -0
- package/dist/lib/toolbox/display.js +56 -0
- package/dist/lib/toolbox/display.js.map +1 -0
- package/dist/lib/toolbox/index.d.ts +5 -0
- package/dist/lib/toolbox/index.js +28 -0
- package/dist/lib/toolbox/index.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/_create_random_file.d.ts +4 -0
- package/dist/lib/toolbox/with_openssl/_create_random_file.js +50 -0
- package/dist/lib/toolbox/with_openssl/_create_random_file.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/_env.d.ts +58 -0
- package/dist/lib/toolbox/with_openssl/_env.js +126 -0
- package/dist/lib/toolbox/with_openssl/_env.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/create_certificate_signing_request.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/create_certificate_signing_request.js +72 -0
- package/dist/lib/toolbox/with_openssl/create_certificate_signing_request.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/create_private_key.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/create_private_key.js +92 -0
- package/dist/lib/toolbox/with_openssl/create_private_key.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/create_self_signed_certificate.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/create_self_signed_certificate.js +135 -0
- package/dist/lib/toolbox/with_openssl/create_self_signed_certificate.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/execute_openssl.d.ts +67 -0
- package/dist/lib/toolbox/with_openssl/execute_openssl.js +246 -0
- package/dist/lib/toolbox/with_openssl/execute_openssl.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/index.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/index.js +30 -0
- package/dist/lib/toolbox/with_openssl/index.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/install_prerequisite.d.ts +7 -0
- package/dist/lib/toolbox/with_openssl/install_prerequisite.js +358 -0
- package/dist/lib/toolbox/with_openssl/install_prerequisite.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/toolbox.d.ts +53 -0
- package/dist/lib/toolbox/with_openssl/toolbox.js +190 -0
- package/dist/lib/toolbox/with_openssl/toolbox.js.map +1 -0
- package/dist/lib/toolbox/without_openssl/create_certificate_signing_request.d.ts +5 -0
- package/dist/lib/toolbox/without_openssl/create_certificate_signing_request.js +69 -0
- package/dist/lib/toolbox/without_openssl/create_certificate_signing_request.js.map +1 -0
- package/dist/lib/toolbox/without_openssl/create_self_signed_certificate.d.ts +3 -0
- package/dist/lib/toolbox/without_openssl/create_self_signed_certificate.js +78 -0
- package/dist/lib/toolbox/without_openssl/create_self_signed_certificate.js.map +1 -0
- package/dist/lib/toolbox/without_openssl/index.d.ts +2 -0
- package/dist/lib/toolbox/without_openssl/index.js +25 -0
- package/dist/lib/toolbox/without_openssl/index.js.map +1 -0
- package/package.json +12 -31
- package/dist/bin/install_prerequisite.mjs +0 -18
- package/dist/bin/install_prerequisite.mjs.map +0 -1
- package/dist/bin/pki.mjs +0 -5932
- package/dist/bin/pki.mjs.map +0 -1
- package/dist/chunk-EQ4DGI4M.mjs +0 -1917
- package/dist/chunk-EQ4DGI4M.mjs.map +0 -1
- package/dist/chunk-GCHH54PS.mjs +0 -30
- package/dist/chunk-GCHH54PS.mjs.map +0 -1
- package/dist/core-BwqSJPHc.d.ts +0 -1041
- package/dist/core.d.mts +0 -2
- package/dist/core.d.ts +0 -2
- package/dist/core.js +0 -1902
- package/dist/core.js.map +0 -1
- package/dist/core.mjs +0 -21
- package/dist/core.mjs.map +0 -1
- package/dist/index.d.mts +0 -1003
- package/dist/index.js +0 -5009
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -3145
- package/dist/index.mjs.map +0 -1
package/bin/pki.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install_prerequisite.js","sourceRoot":"","sources":["../../bin/install_prerequisite.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qDAAqD,CAAC;AAE3F,oBAAoB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACxC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC"}
|
package/dist/bin/pki.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pki.js","sourceRoot":"","sources":["../../bin/pki.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAEjE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type Params, type ProcessAltNamesParam } from "../../toolbox/index.js";
|
|
2
|
+
import type { CaBackend } from "../core/ca_backend.js";
|
|
3
|
+
import type { CertificateAuthorityCore } from "../core/certificate_authority_core.js";
|
|
4
|
+
/**
|
|
5
|
+
* A native (pure-JS, no `openssl` child process) {@link CaBackend}: it
|
|
6
|
+
* bootstraps a CA, signs end-entity and subordinate-CA requests, revokes,
|
|
7
|
+
* and builds CRLs entirely through `node-opcua-crypto`'s signing
|
|
8
|
+
* primitives and {@link CaDatabase}'s write path, so the resulting
|
|
9
|
+
* `index.txt`/`serial`/`crlnumber`/`certs/` are the same on-disk format
|
|
10
|
+
* `openssl ca` produces and an install can move between backends.
|
|
11
|
+
*
|
|
12
|
+
* The signing key reaches every operation through
|
|
13
|
+
* `CertificateAuthority._getSigningKey()`, which yields either the on-disk
|
|
14
|
+
* key or an external `CaSigner`. Nothing below can tell the difference,
|
|
15
|
+
* which is the point: a CA whose key lives in an HSM never has a
|
|
16
|
+
* `private/cakey.pem` and never needs one.
|
|
17
|
+
*
|
|
18
|
+
* Two deliberate differences from the openssl backend, both improvements:
|
|
19
|
+
* a subordinate CA's certificate is recorded in the issuer's `index.txt`
|
|
20
|
+
* (`openssl x509 -CAserial` bumps the serial file but records nothing),
|
|
21
|
+
* and a subordinate's SAN is taken from its own CSR rather than being
|
|
22
|
+
* stamped with the issuer's.
|
|
23
|
+
*/
|
|
24
|
+
export declare class NativeCaBackend implements CaBackend {
|
|
25
|
+
#private;
|
|
26
|
+
/** Nothing to check: this backend spawns no process and needs no tool on PATH. */
|
|
27
|
+
/** Signing goes through `ca._getSigningKey()`, which may be an external signer. */
|
|
28
|
+
readonly supportsExternalSigner = true;
|
|
29
|
+
preflight(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Write a CSR for the CA's own key, the `[v3_ca_req]` equivalent. The
|
|
32
|
+
* key comes from the CA rather than from `privateKeyFile`: on a
|
|
33
|
+
* signer-backed CA that file does not exist.
|
|
34
|
+
*/
|
|
35
|
+
generateCaCsr(ca: CertificateAuthorityCore, _caRootDir: string, _privateKeyFile: string, csrFile: string): Promise<void>;
|
|
36
|
+
bootstrap(ca: CertificateAuthorityCore): Promise<void>;
|
|
37
|
+
/** Sign a subordinate CA's request with this CA's key, the `[v3_ca]` equivalent. */
|
|
38
|
+
signSubordinateCsr(ca: CertificateAuthorityCore, csrFile: string, certFile: string, validityDays: number): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Self-sign a certificate with a caller-supplied key file and record it
|
|
41
|
+
* in this CA's database: the native equivalent of `openssl req -new`
|
|
42
|
+
* followed by `openssl ca -selfsign`, which likewise applies the
|
|
43
|
+
* end-entity profile and updates `index.txt`.
|
|
44
|
+
*/
|
|
45
|
+
createSelfSignedCertificate(ca: CertificateAuthorityCore, certificateFile: string, privateKeyFile: string, params: Params): Promise<void>;
|
|
46
|
+
signEndEntityCsr(ca: CertificateAuthorityCore, certificate: string, csr: string, params: Params, sanOverride: Required<ProcessAltNamesParam>): Promise<void>;
|
|
47
|
+
regenerateCrl(ca: CertificateAuthorityCore): Promise<void>;
|
|
48
|
+
revoke(ca: CertificateAuthorityCore, certificate: string, reason: string): Promise<void>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// node-opcua-pki
|
|
3
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org
|
|
5
|
+
// Copyright (c) 2022-2026 - Sterfive.com
|
|
6
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
//
|
|
8
|
+
// This project is licensed under the terms of the MIT license.
|
|
9
|
+
//
|
|
10
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
11
|
+
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
12
|
+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
13
|
+
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
14
|
+
//
|
|
15
|
+
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
16
|
+
// Software.
|
|
17
|
+
//
|
|
18
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
19
|
+
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
20
|
+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
21
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
23
|
+
import fs from "node:fs";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
import { CertificatePurpose, createCertificateFromCsr, createCertificateSigningRequest, createCrl, isCaSigner, privateKeyToCryptoKey, readPrivateKey, Subject, x509 } from "node-opcua-crypto";
|
|
26
|
+
import { displaySubtitle, displayTitle } from "../../toolbox/index.js";
|
|
27
|
+
import { CaDatabase } from "../core/ca_database.js";
|
|
28
|
+
/** The CA-certificate lifetime the openssl backend hard-codes (`x509 -req -days 3650`). */
|
|
29
|
+
const CA_CERT_VALIDITY_DAYS = 3650;
|
|
30
|
+
const RSA_SHA256 = { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } };
|
|
31
|
+
/** A signer declares its own algorithm; a raw key is always the RSA/SHA-256 this CA generates. */
|
|
32
|
+
function signingAlgorithmOf(key) {
|
|
33
|
+
return isCaSigner(key) ? key.algorithm : RSA_SHA256;
|
|
34
|
+
}
|
|
35
|
+
function daysFromNow(notBefore, days) {
|
|
36
|
+
return new Date(notBefore.getTime() + days * 24 * 60 * 60 * 1000);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The SAN every CA certificate carries. RFC 5280 does not require one on a
|
|
40
|
+
* CA certificate, but the OPC UA profile does, and validators (UaExpert,
|
|
41
|
+
* the compliance tools) reject a CA without it - so mirror what the
|
|
42
|
+
* openssl backend puts in `[v3_ca]`: `URI:urn:<commonName>`.
|
|
43
|
+
*/
|
|
44
|
+
function caSanUri(ca) {
|
|
45
|
+
return `urn:${ca.subject.commonName || "NodeOPCUA-CA"}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The subject alternative names a CSR asked for, in the shape the signing
|
|
49
|
+
* primitive wants. `openssl ca` does not copy SANs across from the CSR
|
|
50
|
+
* (openssl/openssl#10458), which is why the caller has to re-derive them;
|
|
51
|
+
* peculiar decodes IP addresses to dotted form for us.
|
|
52
|
+
*/
|
|
53
|
+
function sanFromCsr(csrPem) {
|
|
54
|
+
const request = new x509.Pkcs10CertificateRequest(csrPem);
|
|
55
|
+
const extension = request.getExtension("2.5.29.17");
|
|
56
|
+
const dns = [];
|
|
57
|
+
const ip = [];
|
|
58
|
+
let applicationUri;
|
|
59
|
+
for (const name of extension?.names.toJSON() ?? []) {
|
|
60
|
+
if (name.type === "dns") {
|
|
61
|
+
dns.push(name.value);
|
|
62
|
+
}
|
|
63
|
+
else if (name.type === "ip") {
|
|
64
|
+
ip.push(name.value);
|
|
65
|
+
}
|
|
66
|
+
else if (name.type === "url" && applicationUri === undefined) {
|
|
67
|
+
applicationUri = name.value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { dns, ip, applicationUri };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Maps this codebase's CRL revocation reason strings (see
|
|
74
|
+
* `CertificateAuthority.revokeCertificate`'s `crlReasons` list) to
|
|
75
|
+
* `@peculiar/x509`'s `X509CrlReason` enum keys — same reasons, but
|
|
76
|
+
* `X509CrlReason.cACompromise` is lowercase-first where this codebase's
|
|
77
|
+
* `"CACompromise"` is not.
|
|
78
|
+
*/
|
|
79
|
+
const REASON_TO_X509_CRL_REASON = {
|
|
80
|
+
unspecified: x509.X509CrlReason.unspecified,
|
|
81
|
+
keyCompromise: x509.X509CrlReason.keyCompromise,
|
|
82
|
+
CACompromise: x509.X509CrlReason.cACompromise,
|
|
83
|
+
affiliationChanged: x509.X509CrlReason.affiliationChanged,
|
|
84
|
+
superseded: x509.X509CrlReason.superseded,
|
|
85
|
+
cessationOfOperation: x509.X509CrlReason.cessationOfOperation,
|
|
86
|
+
certificateHold: x509.X509CrlReason.certificateHold,
|
|
87
|
+
removeFromCRL: x509.X509CrlReason.removeFromCRL
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Builds OpenSSL's slash-delimited one-line subject (`"/CN=Leaf/O=Acme"`)
|
|
91
|
+
* from the certificate's parsed subject attributes — NOT by re-splitting
|
|
92
|
+
* `Name.toString()`. The subject comes verbatim from the requester's CSR,
|
|
93
|
+
* so it is attacker-controlled; the string form escapes `,` (which a
|
|
94
|
+
* `split(",")` would then mangle) and, because its control-character
|
|
95
|
+
* `replace()` has no `g` flag, escapes only the FIRST `\n`/`\t` per value,
|
|
96
|
+
* letting later ones through raw — which would let a crafted CN inject a
|
|
97
|
+
* forged row into the tab/newline-delimited `index.txt`. Working from
|
|
98
|
+
* `toJSON()` sidesteps that entirely; {@link CaDatabase} additionally
|
|
99
|
+
* escapes every control character it writes, as `X509_NAME_oneline` does.
|
|
100
|
+
*/
|
|
101
|
+
function toOpenSslSubjectString(subjectName) {
|
|
102
|
+
const parts = [];
|
|
103
|
+
for (const rdn of subjectName.toJSON()) {
|
|
104
|
+
for (const [type, values] of Object.entries(rdn)) {
|
|
105
|
+
for (const value of values) {
|
|
106
|
+
parts.push(`${type}=${value}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return `/${parts.join("/")}`;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A native (pure-JS, no `openssl` child process) {@link CaBackend}: it
|
|
114
|
+
* bootstraps a CA, signs end-entity and subordinate-CA requests, revokes,
|
|
115
|
+
* and builds CRLs entirely through `node-opcua-crypto`'s signing
|
|
116
|
+
* primitives and {@link CaDatabase}'s write path, so the resulting
|
|
117
|
+
* `index.txt`/`serial`/`crlnumber`/`certs/` are the same on-disk format
|
|
118
|
+
* `openssl ca` produces and an install can move between backends.
|
|
119
|
+
*
|
|
120
|
+
* The signing key reaches every operation through
|
|
121
|
+
* `CertificateAuthority._getSigningKey()`, which yields either the on-disk
|
|
122
|
+
* key or an external `CaSigner`. Nothing below can tell the difference,
|
|
123
|
+
* which is the point: a CA whose key lives in an HSM never has a
|
|
124
|
+
* `private/cakey.pem` and never needs one.
|
|
125
|
+
*
|
|
126
|
+
* Two deliberate differences from the openssl backend, both improvements:
|
|
127
|
+
* a subordinate CA's certificate is recorded in the issuer's `index.txt`
|
|
128
|
+
* (`openssl x509 -CAserial` bumps the serial file but records nothing),
|
|
129
|
+
* and a subordinate's SAN is taken from its own CSR rather than being
|
|
130
|
+
* stamped with the issuer's.
|
|
131
|
+
*/
|
|
132
|
+
export class NativeCaBackend {
|
|
133
|
+
/** Nothing to check: this backend spawns no process and needs no tool on PATH. */
|
|
134
|
+
/** Signing goes through `ca._getSigningKey()`, which may be an external signer. */
|
|
135
|
+
supportsExternalSigner = true;
|
|
136
|
+
async preflight() {
|
|
137
|
+
// intentionally empty
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Write a CSR for the CA's own key, the `[v3_ca_req]` equivalent. The
|
|
141
|
+
* key comes from the CA rather than from `privateKeyFile`: on a
|
|
142
|
+
* signer-backed CA that file does not exist.
|
|
143
|
+
*/
|
|
144
|
+
async generateCaCsr(ca, _caRootDir, _privateKeyFile, csrFile) {
|
|
145
|
+
displayTitle("Generate a certificate request for the CA key");
|
|
146
|
+
const signingKey = await ca._getSigningKey();
|
|
147
|
+
const { csr } = await createCertificateSigningRequest({
|
|
148
|
+
privateKey: signingKey,
|
|
149
|
+
subject: ca.subject.toString(),
|
|
150
|
+
applicationUri: caSanUri(ca),
|
|
151
|
+
purpose: CertificatePurpose.ForCertificateAuthority
|
|
152
|
+
});
|
|
153
|
+
await fs.promises.writeFile(csrFile, csr);
|
|
154
|
+
}
|
|
155
|
+
async bootstrap(ca) {
|
|
156
|
+
const caRootDir = path.resolve(ca.rootDir);
|
|
157
|
+
const csrFile = path.join(caRootDir, "private/cakey.csr");
|
|
158
|
+
await this.generateCaCsr(ca, caRootDir, path.join(caRootDir, "private/cakey.pem"), csrFile);
|
|
159
|
+
const issuerCA = ca._issuerCA;
|
|
160
|
+
if (issuerCA) {
|
|
161
|
+
displayTitle("Generate CA Certificate (signed by issuer CA)");
|
|
162
|
+
// The issuer's serial file and database are mutated here, so the
|
|
163
|
+
// issuer's own lock is required - the caller only holds this
|
|
164
|
+
// (subordinate) CA's. Subordinate -> issuer is the only cross-CA
|
|
165
|
+
// lock edge in this codebase and it is never reversed, so it
|
|
166
|
+
// cannot deadlock; the exception is two CAs sharing one rootDir,
|
|
167
|
+
// where the lock is already held and re-acquiring the
|
|
168
|
+
// non-reentrant file lock would deadlock against itself.
|
|
169
|
+
const signWithIssuer = () => this.signSubordinateCsr(issuerCA, csrFile, ca.caCertificate, CA_CERT_VALIDITY_DAYS);
|
|
170
|
+
if (path.resolve(issuerCA.rootDir) === caRootDir) {
|
|
171
|
+
await signWithIssuer();
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
await issuerCA._withCaDirectoryLock(signWithIssuer);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
displayTitle("Generate CA Certificate (self-signed)");
|
|
179
|
+
const csrPem = await fs.promises.readFile(csrFile, "utf-8");
|
|
180
|
+
const signingKey = await ca._getSigningKey();
|
|
181
|
+
const request = new x509.Pkcs10CertificateRequest(csrPem);
|
|
182
|
+
const notBefore = new Date();
|
|
183
|
+
const { cert } = await createCertificateFromCsr({
|
|
184
|
+
csr: csrPem,
|
|
185
|
+
// the CSR's own parsed subject, so issuer and subject are
|
|
186
|
+
// byte-identical on a self-signed root: re-encoding a string
|
|
187
|
+
// form could differ and break chain building
|
|
188
|
+
issuerName: request.subjectName,
|
|
189
|
+
issuerPublicKey: request.publicKey,
|
|
190
|
+
signingKey,
|
|
191
|
+
signingAlgorithm: signingAlgorithmOf(signingKey),
|
|
192
|
+
notBefore,
|
|
193
|
+
notAfter: daysFromNow(notBefore, CA_CERT_VALIDITY_DAYS),
|
|
194
|
+
purpose: CertificatePurpose.ForCertificateAuthority,
|
|
195
|
+
applicationUri: caSanUri(ca),
|
|
196
|
+
revocation: {
|
|
197
|
+
crlDistributionUrl: ca.crlDistributionUrl,
|
|
198
|
+
ocspResponderUrl: ca.ocspResponderUrl,
|
|
199
|
+
caIssuersUrl: ca.caIssuersUrl
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
await fs.promises.writeFile(ca.caCertificate, cert);
|
|
203
|
+
}
|
|
204
|
+
displaySubtitle("generate initial CRL (Certificate Revocation List)");
|
|
205
|
+
await this.#regenerateCrlLocked(ca, new CaDatabase(ca.rootDir));
|
|
206
|
+
displayTitle("Create Certificate Authority (CA) ---> DONE");
|
|
207
|
+
}
|
|
208
|
+
/** Sign a subordinate CA's request with this CA's key, the `[v3_ca]` equivalent. */
|
|
209
|
+
async signSubordinateCsr(ca, csrFile, certFile, validityDays) {
|
|
210
|
+
const { signingKey, signingAlgorithm, issuerPublicKey, issuerName } = await this.#issuerContext(ca);
|
|
211
|
+
const csrPem = await fs.promises.readFile(csrFile, "utf-8");
|
|
212
|
+
const db = new CaDatabase(ca.rootDir);
|
|
213
|
+
const serialNumber = db.nextSerial();
|
|
214
|
+
const notBefore = new Date();
|
|
215
|
+
const notAfter = daysFromNow(notBefore, validityDays);
|
|
216
|
+
const { cert } = await createCertificateFromCsr({
|
|
217
|
+
csr: csrPem,
|
|
218
|
+
issuerName,
|
|
219
|
+
issuerPublicKey,
|
|
220
|
+
signingKey,
|
|
221
|
+
signingAlgorithm,
|
|
222
|
+
serialNumber,
|
|
223
|
+
notBefore,
|
|
224
|
+
notAfter,
|
|
225
|
+
purpose: CertificatePurpose.ForCertificateAuthority,
|
|
226
|
+
// the subordinate's own SAN, not the issuer's
|
|
227
|
+
...sanFromCsr(csrPem),
|
|
228
|
+
revocation: {
|
|
229
|
+
crlDistributionUrl: ca.crlDistributionUrl,
|
|
230
|
+
ocspResponderUrl: ca.ocspResponderUrl,
|
|
231
|
+
caIssuersUrl: ca.caIssuersUrl
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
await fs.promises.writeFile(certFile, cert);
|
|
235
|
+
this.#record(db, serialNumber, cert, notAfter);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Self-sign a certificate with a caller-supplied key file and record it
|
|
239
|
+
* in this CA's database: the native equivalent of `openssl req -new`
|
|
240
|
+
* followed by `openssl ca -selfsign`, which likewise applies the
|
|
241
|
+
* end-entity profile and updates `index.txt`.
|
|
242
|
+
*/
|
|
243
|
+
async createSelfSignedCertificate(ca, certificateFile, privateKeyFile, params) {
|
|
244
|
+
displaySubtitle("- the certificate signing request");
|
|
245
|
+
const key = await privateKeyToCryptoKey(readPrivateKey(privateKeyFile, await ca._privateKeyPassphrase()));
|
|
246
|
+
const { csr } = await createCertificateSigningRequest({
|
|
247
|
+
privateKey: key,
|
|
248
|
+
subject: params.subject ? new Subject(params.subject).toString() : ca.subject.toString(),
|
|
249
|
+
dns: params.dns,
|
|
250
|
+
ip: params.ip,
|
|
251
|
+
applicationUri: params.applicationUri,
|
|
252
|
+
purpose: CertificatePurpose.ForApplication
|
|
253
|
+
});
|
|
254
|
+
displaySubtitle("- creating the self-signed certificate");
|
|
255
|
+
const request = new x509.Pkcs10CertificateRequest(csr);
|
|
256
|
+
const db = new CaDatabase(ca.rootDir);
|
|
257
|
+
const serialNumber = db.nextSerial();
|
|
258
|
+
const notBefore = params.startDate ?? new Date();
|
|
259
|
+
const notAfter = params.endDate ?? daysFromNow(notBefore, params.validity ?? 365);
|
|
260
|
+
const { cert } = await createCertificateFromCsr({
|
|
261
|
+
csr,
|
|
262
|
+
issuerName: request.subjectName,
|
|
263
|
+
issuerPublicKey: request.publicKey,
|
|
264
|
+
signingKey: key,
|
|
265
|
+
signingAlgorithm: RSA_SHA256,
|
|
266
|
+
serialNumber,
|
|
267
|
+
notBefore,
|
|
268
|
+
notAfter,
|
|
269
|
+
purpose: CertificatePurpose.ForApplication,
|
|
270
|
+
...sanFromCsr(csr)
|
|
271
|
+
});
|
|
272
|
+
await fs.promises.writeFile(certificateFile, cert);
|
|
273
|
+
this.#record(db, serialNumber, cert, notAfter);
|
|
274
|
+
}
|
|
275
|
+
/** `certs/<SERIAL>.pem` plus the `V` row, exactly as `openssl ca` writes them. */
|
|
276
|
+
#record(db, serialNumber, certPem, notAfter) {
|
|
277
|
+
db.storeCertificate(serialNumber, certPem);
|
|
278
|
+
db.appendIssued({
|
|
279
|
+
serial: serialNumber,
|
|
280
|
+
expiryDate: notAfter,
|
|
281
|
+
subject: toOpenSslSubjectString(new x509.X509Certificate(certPem).subjectName)
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The CA's signing key and issuer identity, resolved fresh on every
|
|
286
|
+
* call and never cached across operations. The identity is read back
|
|
287
|
+
* from the CA certificate on disk so that the issuer field of anything
|
|
288
|
+
* this CA signs is byte-identical to that certificate's subject.
|
|
289
|
+
*/
|
|
290
|
+
async #issuerContext(ca) {
|
|
291
|
+
const signingKey = await ca._getSigningKey();
|
|
292
|
+
const caCertPem = await fs.promises.readFile(ca.caCertificate, "utf-8");
|
|
293
|
+
const caCert = new x509.X509Certificate(caCertPem);
|
|
294
|
+
return {
|
|
295
|
+
signingKey,
|
|
296
|
+
signingAlgorithm: signingAlgorithmOf(signingKey),
|
|
297
|
+
issuerPublicKey: caCert.publicKey,
|
|
298
|
+
issuerName: caCert.subjectName
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
async signEndEntityCsr(ca, certificate, csr, params, sanOverride) {
|
|
302
|
+
const { signingKey, signingAlgorithm, issuerPublicKey, issuerName } = await this.#issuerContext(ca);
|
|
303
|
+
const db = new CaDatabase(ca.rootDir);
|
|
304
|
+
const serialNumber = db.nextSerial();
|
|
305
|
+
const csrPem = await fs.promises.readFile(csr, "utf-8");
|
|
306
|
+
const notBefore = params.startDate ?? new Date();
|
|
307
|
+
const notAfter = params.endDate ?? new Date(notBefore.getTime() + (params.validity ?? 365) * 24 * 60 * 60 * 1000);
|
|
308
|
+
const { cert } = await createCertificateFromCsr({
|
|
309
|
+
csr: csrPem,
|
|
310
|
+
issuerName,
|
|
311
|
+
issuerPublicKey,
|
|
312
|
+
signingKey,
|
|
313
|
+
signingAlgorithm,
|
|
314
|
+
serialNumber,
|
|
315
|
+
notBefore,
|
|
316
|
+
notAfter,
|
|
317
|
+
purpose: CertificatePurpose.ForApplication,
|
|
318
|
+
dns: sanOverride.dns,
|
|
319
|
+
ip: sanOverride.ip,
|
|
320
|
+
applicationUri: sanOverride.applicationUri,
|
|
321
|
+
revocation: {
|
|
322
|
+
crlDistributionUrl: ca.crlDistributionUrl,
|
|
323
|
+
ocspResponderUrl: ca.ocspResponderUrl,
|
|
324
|
+
caIssuersUrl: ca.caIssuersUrl
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
await fs.promises.writeFile(certificate, cert);
|
|
328
|
+
this.#record(db, serialNumber, cert, notAfter);
|
|
329
|
+
}
|
|
330
|
+
async #regenerateCrlLocked(ca, db) {
|
|
331
|
+
const { signingKey, signingAlgorithm, issuerPublicKey, issuerName } = await this.#issuerContext(ca);
|
|
332
|
+
const crlNumber = db.nextCrlNumber();
|
|
333
|
+
const entries = db
|
|
334
|
+
.readIndex()
|
|
335
|
+
.filter((r) => r.status === "revoked")
|
|
336
|
+
.map((r) => ({
|
|
337
|
+
serialNumber: r.serial,
|
|
338
|
+
revocationDate: r.revocationDate ? new Date(r.revocationDate) : new Date(),
|
|
339
|
+
reason: r.reason ? REASON_TO_X509_CRL_REASON[r.reason] : undefined
|
|
340
|
+
}));
|
|
341
|
+
const { crl } = await createCrl({
|
|
342
|
+
issuerName,
|
|
343
|
+
issuerPublicKey,
|
|
344
|
+
signingKey,
|
|
345
|
+
signingAlgorithm,
|
|
346
|
+
crlNumber: BigInt(`0x${crlNumber}`),
|
|
347
|
+
entries
|
|
348
|
+
});
|
|
349
|
+
await fs.promises.writeFile(ca.revocationList, crl);
|
|
350
|
+
const der = new x509.X509Crl(crl).rawData;
|
|
351
|
+
await fs.promises.writeFile(ca.revocationListDER, Buffer.from(der));
|
|
352
|
+
}
|
|
353
|
+
async regenerateCrl(ca) {
|
|
354
|
+
const db = new CaDatabase(ca.rootDir);
|
|
355
|
+
await this.#regenerateCrlLocked(ca, db);
|
|
356
|
+
}
|
|
357
|
+
async revoke(ca, certificate, reason) {
|
|
358
|
+
const certPem = await fs.promises.readFile(certificate, "utf-8");
|
|
359
|
+
const cert = new x509.X509Certificate(certPem);
|
|
360
|
+
const db = new CaDatabase(ca.rootDir);
|
|
361
|
+
db.markRevoked(cert.serialNumber, new Date(), reason);
|
|
362
|
+
await this.#regenerateCrlLocked(ca, db);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=native_ca_backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native_ca_backend.js","sourceRoot":"","sources":["../../../../lib/ca/backends/native_ca_backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Params, type ProcessAltNamesParam } from "../../toolbox/index.js";
|
|
2
|
+
import type { CaBackend } from "../core/ca_backend.js";
|
|
3
|
+
import type { CertificateAuthorityCore } from "../core/certificate_authority_core.js";
|
|
4
|
+
/**
|
|
5
|
+
* Every render of `conf/caconfig.cnf` needs `ALTNAME` / `CDP_URL` /
|
|
6
|
+
* `AIA_VALUE` resolved, **even for an `openssl` subcommand that only reads
|
|
7
|
+
* a different section** (`ca -gencrl` only needs `[crl_ext]`, `ca -revoke`
|
|
8
|
+
* only needs `[ca]`): openssl's config loader (`NCONF_load`) expands every
|
|
9
|
+
* `$ENV::NAME` reference in the file line by line as it parses it, not
|
|
10
|
+
* lazily per queried section, and every section in this template — not
|
|
11
|
+
* just the two gated behind `{{#CDP_URL}}` / `{{#AIA_VALUE}}` — references
|
|
12
|
+
* `$ENV::ALTNAME` unconditionally. Leaving any of the three unresolved
|
|
13
|
+
* makes openssl fall through to its own native `$ENV::` resolution (a real
|
|
14
|
+
* OS environment variable, which is never set) and fail with "variable has
|
|
15
|
+
* no value".
|
|
16
|
+
*
|
|
17
|
+
* Passed explicitly rather than relying on whatever `setEnv()` last wrote
|
|
18
|
+
* to the shared registry (see {@link generateStaticConfig}'s
|
|
19
|
+
* `envOverrides`) — empty string means "omit the extension" for the two
|
|
20
|
+
* gated keys (the template's `{{#KEY}}` block strips itself on an empty
|
|
21
|
+
* value), never "fall back to the registry".
|
|
22
|
+
*
|
|
23
|
+
* Exported as the single implementation of the CDP/AIA value format:
|
|
24
|
+
* `CertificateAuthority._wireRevocationEnvVars` (the legacy registry shim)
|
|
25
|
+
* delegates here so the format cannot drift between the two mechanisms.
|
|
26
|
+
*/
|
|
27
|
+
export declare function caConfigEnvOverrides(ca: CertificateAuthorityCore, altName?: string): Record<string, string>;
|
|
28
|
+
/**
|
|
29
|
+
* The default {@link CaBackend}: shells out to the `openssl` CLI, exactly as
|
|
30
|
+
* `CertificateAuthority` always has — this is a pure code move (plus a lock
|
|
31
|
+
* around every database-mutating operation, temp-config cleanup, and
|
|
32
|
+
* explicit `envOverrides` on every config render) with no change in the
|
|
33
|
+
* openssl commands issued or the files produced.
|
|
34
|
+
*/
|
|
35
|
+
export declare class OpenSslCaBackend implements CaBackend {
|
|
36
|
+
#private;
|
|
37
|
+
/** The openssl CLI loads its key from a file, so it cannot call out to an HSM. */
|
|
38
|
+
readonly supportsExternalSigner = false;
|
|
39
|
+
preflight(): Promise<void>;
|
|
40
|
+
generateCaCsr(ca: CertificateAuthorityCore, _caRootDir: string, privateKeyFile: string, csrFile: string): Promise<void>;
|
|
41
|
+
bootstrap(ca: CertificateAuthorityCore): Promise<void>;
|
|
42
|
+
regenerateCrl(ca: CertificateAuthorityCore): Promise<void>;
|
|
43
|
+
signSubordinateCsr(ca: CertificateAuthorityCore, csrFile: string, certFile: string, validityDays: number): Promise<void>;
|
|
44
|
+
signEndEntityCsr(ca: CertificateAuthorityCore, certificate: string, csr: string, params1: Params, sanOverride: Required<ProcessAltNamesParam>): Promise<void>;
|
|
45
|
+
revoke(ca: CertificateAuthorityCore, certificate: string, reason: string): Promise<void>;
|
|
46
|
+
createSelfSignedCertificate(ca: CertificateAuthorityCore, certificateFile: string, privateKeyFile: string, params: Params): Promise<void>;
|
|
47
|
+
}
|