@harperfast/integration-testing 0.1.0 → 0.3.0-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.
Files changed (56) hide show
  1. package/README.md +71 -5
  2. package/dist/harperLifecycle.d.ts +176 -0
  3. package/dist/harperLifecycle.js +71 -40
  4. package/dist/harperLifecycle.js.map +1 -1
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/loopbackAddressPool.d.ts +50 -0
  9. package/dist/run.d.ts +2 -0
  10. package/dist/security/certGenUtils.d.ts +52 -0
  11. package/dist/security/certGenUtils.js +170 -0
  12. package/dist/security/certGenUtils.js.map +1 -0
  13. package/dist/security/crl/generate-test-certs.d.ts +34 -0
  14. package/dist/security/crl/generate-test-certs.js +81 -0
  15. package/dist/security/crl/generate-test-certs.js.map +1 -0
  16. package/dist/security/ocsp/generate-test-certs.d.ts +55 -0
  17. package/dist/security/ocsp/generate-test-certs.js +106 -0
  18. package/dist/security/ocsp/generate-test-certs.js.map +1 -0
  19. package/dist/security/ocspServer.d.ts +18 -0
  20. package/dist/security/ocspServer.js +132 -0
  21. package/dist/security/ocspServer.js.map +1 -0
  22. package/dist/securityServices.d.ts +49 -0
  23. package/dist/securityServices.js +120 -0
  24. package/dist/securityServices.js.map +1 -0
  25. package/dist/src/harperLifecycle.d.ts +156 -0
  26. package/dist/src/harperLifecycle.js +315 -0
  27. package/dist/src/harperLifecycle.js.map +1 -0
  28. package/dist/src/index.d.ts +3 -0
  29. package/dist/src/index.js +4 -0
  30. package/dist/src/index.js.map +1 -0
  31. package/dist/src/loopbackAddressPool.d.ts +50 -0
  32. package/dist/src/loopbackAddressPool.js +337 -0
  33. package/dist/src/loopbackAddressPool.js.map +1 -0
  34. package/dist/src/run.d.ts +2 -0
  35. package/dist/src/run.js +94 -0
  36. package/dist/src/run.js.map +1 -0
  37. package/dist/src/security/certGenUtils.d.ts +52 -0
  38. package/dist/src/security/certGenUtils.js +170 -0
  39. package/dist/src/security/certGenUtils.js.map +1 -0
  40. package/dist/src/security/crl/generate-test-certs.d.ts +34 -0
  41. package/dist/src/security/crl/generate-test-certs.js +81 -0
  42. package/dist/src/security/crl/generate-test-certs.js.map +1 -0
  43. package/dist/src/security/ocsp/generate-test-certs.d.ts +55 -0
  44. package/dist/src/security/ocsp/generate-test-certs.js +106 -0
  45. package/dist/src/security/ocsp/generate-test-certs.js.map +1 -0
  46. package/dist/src/security/ocspServer.d.ts +18 -0
  47. package/dist/src/security/ocspServer.js +132 -0
  48. package/dist/src/security/ocspServer.js.map +1 -0
  49. package/dist/src/securityServices.d.ts +49 -0
  50. package/dist/src/securityServices.js +120 -0
  51. package/dist/src/securityServices.js.map +1 -0
  52. package/dist/src/targz.d.ts +6 -0
  53. package/dist/src/targz.js +20 -0
  54. package/dist/src/targz.js.map +1 -0
  55. package/dist/targz.d.ts +6 -0
  56. package/package.json +5 -3
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Pure Node.js X.509 certificate and CRL generation utilities
3
+ *
4
+ * Uses Node.js built-in webcrypto (Ed25519) + pkijs for ASN.1 encoding.
5
+ * No openssl CLI dependency — fully portable across macOS and Linux.
6
+ */
7
+ import * as pkijs from 'pkijs';
8
+ declare const OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
9
+ declare const CLIENT_AUTH_OID = "1.3.6.1.5.5.7.3.2";
10
+ export interface Ed25519KeyPair {
11
+ privateKey: CryptoKey;
12
+ publicKey: CryptoKey;
13
+ /** PKCS8 PEM string */
14
+ privateKeyPem: string;
15
+ }
16
+ export declare function generateEd25519KeyPair(): Promise<Ed25519KeyPair>;
17
+ /** Convert a pkijs Certificate to PEM string */
18
+ export declare function certToPem(cert: pkijs.Certificate): string;
19
+ /** Convert a pkijs CertificateRevocationList to PEM string */
20
+ export declare function crlToPem(crl: pkijs.CertificateRevocationList): string;
21
+ interface CertOptions {
22
+ serialNumber: number;
23
+ subject: {
24
+ CN: string;
25
+ O?: string;
26
+ };
27
+ issuer: {
28
+ CN: string;
29
+ O?: string;
30
+ };
31
+ validDays: number;
32
+ issuerKey: CryptoKey;
33
+ subjectPublicKey: CryptoKey;
34
+ isCA?: boolean;
35
+ extensions?: pkijs.Extension[];
36
+ }
37
+ /** Create a signed Ed25519 X.509 v3 certificate */
38
+ export declare function createCertificate(opts: CertOptions): Promise<pkijs.Certificate>;
39
+ /** Create a CRL Distribution Points extension */
40
+ export declare function makeCRLDistributionPointsExt(url: string): pkijs.Extension;
41
+ /** Create an Authority Info Access extension with an OCSP URL */
42
+ export declare function makeOCSPAIAExt(url: string): pkijs.Extension;
43
+ /** Create an Extended Key Usage extension */
44
+ export declare function makeExtKeyUsageExt(oids: string[]): pkijs.Extension;
45
+ export { OCSP_SIGNING_OID, CLIENT_AUTH_OID };
46
+ /** Create a signed X.509v2 CRL */
47
+ export declare function createCRL(issuerCert: pkijs.Certificate, issuerKey: CryptoKey, revokedSerials: number[]): Promise<pkijs.CertificateRevocationList>;
48
+ /**
49
+ * Sign a pkijs BasicOCSPResponse with an Ed25519 key.
50
+ * Must be called after tbsResponseData.responses is populated.
51
+ */
52
+ export declare function signBasicOCSPResponse(basicResponse: pkijs.BasicOCSPResponse, privateKey: CryptoKey): Promise<void>;
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Pure Node.js X.509 certificate and CRL generation utilities
3
+ *
4
+ * Uses Node.js built-in webcrypto (Ed25519) + pkijs for ASN.1 encoding.
5
+ * No openssl CLI dependency — fully portable across macOS and Linux.
6
+ */
7
+ import { webcrypto } from 'node:crypto';
8
+ import * as pkijs from 'pkijs';
9
+ import * as asn1js from 'asn1js';
10
+ // Ed25519 OID (RFC 8410)
11
+ const ED25519_OID = '1.3.101.112';
12
+ // Standard extension OIDs
13
+ const BASIC_CONSTRAINTS_OID = '2.5.29.19';
14
+ const CRL_DISTRIBUTION_POINTS_OID = '2.5.29.31';
15
+ const AUTHORITY_INFO_ACCESS_OID = '1.3.6.1.5.5.7.1.1';
16
+ const EXT_KEY_USAGE_OID = '2.5.29.37';
17
+ const OCSP_SIGNING_OID = '1.3.6.1.5.5.7.3.9';
18
+ const CLIENT_AUTH_OID = '1.3.6.1.5.5.7.3.2';
19
+ const OCSP_ACCESS_METHOD_OID = '1.3.6.1.5.5.7.48.1';
20
+ // Configure pkijs to use Node.js webcrypto
21
+ pkijs.setEngine('node', new pkijs.CryptoEngine({ name: 'node', crypto: webcrypto }));
22
+ export async function generateEd25519KeyPair() {
23
+ // Ed25519 is supported at runtime (Node 20+) but @types/node lacks dedicated types for it
24
+ const keyPair = (await webcrypto.subtle.generateKey({ name: 'Ed25519' }, true, [
25
+ 'sign',
26
+ 'verify',
27
+ ]));
28
+ const pkcs8 = await webcrypto.subtle.exportKey('pkcs8', keyPair.privateKey);
29
+ const b64 = Buffer.from(pkcs8).toString('base64');
30
+ const lines = b64.match(/.{1,64}/g).join('\n');
31
+ const privateKeyPem = `-----BEGIN PRIVATE KEY-----\n${lines}\n-----END PRIVATE KEY-----\n`;
32
+ return { privateKey: keyPair.privateKey, publicKey: keyPair.publicKey, privateKeyPem };
33
+ }
34
+ /**
35
+ * Sign a pkijs Certificate or CertificateRevocationList with an Ed25519 key.
36
+ * Bypasses pkijs's sign() method which does not support Ed25519.
37
+ */
38
+ async function signWithEd25519(obj, privateKey) {
39
+ const algId = new pkijs.AlgorithmIdentifier({ algorithmId: ED25519_OID });
40
+ obj.signature = algId;
41
+ obj.signatureAlgorithm = algId;
42
+ const tbsBer = obj.encodeTBS().toBER();
43
+ obj.tbsView = new Uint8Array(tbsBer);
44
+ const sig = await webcrypto.subtle.sign('Ed25519', privateKey, tbsBer);
45
+ obj.signatureValue = new asn1js.BitString({ valueHex: sig });
46
+ }
47
+ /** Convert a pkijs Certificate to PEM string */
48
+ export function certToPem(cert) {
49
+ const der = cert.toSchema(false).toBER();
50
+ const b64 = Buffer.from(der).toString('base64');
51
+ return `-----BEGIN CERTIFICATE-----\n${b64.match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----\n`;
52
+ }
53
+ /** Convert a pkijs CertificateRevocationList to PEM string */
54
+ export function crlToPem(crl) {
55
+ const der = crl.toSchema(false).toBER();
56
+ const b64 = Buffer.from(der).toString('base64');
57
+ return `-----BEGIN X509 CRL-----\n${b64.match(/.{1,64}/g).join('\n')}\n-----END X509 CRL-----\n`;
58
+ }
59
+ /** Create a signed Ed25519 X.509 v3 certificate */
60
+ export async function createCertificate(opts) {
61
+ const cert = new pkijs.Certificate();
62
+ cert.version = 2; // v3
63
+ cert.serialNumber = new asn1js.Integer({ value: opts.serialNumber });
64
+ const now = new Date();
65
+ cert.notBefore.value = now;
66
+ cert.notAfter.value = new Date(now.getTime() + opts.validDays * 24 * 60 * 60 * 1000);
67
+ // Build subject RDN
68
+ const buildRDN = (dn, target) => {
69
+ target.typesAndValues.push(new pkijs.AttributeTypeAndValue({
70
+ type: '2.5.4.3',
71
+ value: new asn1js.Utf8String({ value: dn.CN }),
72
+ }));
73
+ if (dn.O) {
74
+ target.typesAndValues.push(new pkijs.AttributeTypeAndValue({
75
+ type: '2.5.4.10',
76
+ value: new asn1js.Utf8String({ value: dn.O }),
77
+ }));
78
+ }
79
+ };
80
+ buildRDN(opts.subject, cert.subject);
81
+ buildRDN(opts.issuer, cert.issuer);
82
+ // Import public key into SubjectPublicKeyInfo
83
+ const spki = await webcrypto.subtle.exportKey('spki', opts.subjectPublicKey);
84
+ const spkiAsn1 = asn1js.fromBER(spki);
85
+ cert.subjectPublicKeyInfo.fromSchema(spkiAsn1.result);
86
+ // Add basic constraints extension (always present)
87
+ cert.extensions = [];
88
+ const bc = new pkijs.BasicConstraints({ cA: opts.isCA === true });
89
+ cert.extensions.push(new pkijs.Extension({
90
+ extnID: BASIC_CONSTRAINTS_OID,
91
+ critical: true,
92
+ extnValue: bc.toSchema().toBER(),
93
+ }));
94
+ // Add caller-supplied extensions
95
+ if (opts.extensions) {
96
+ cert.extensions.push(...opts.extensions);
97
+ }
98
+ await signWithEd25519(cert, opts.issuerKey);
99
+ return cert;
100
+ }
101
+ /** Create a CRL Distribution Points extension */
102
+ export function makeCRLDistributionPointsExt(url) {
103
+ const dp = new pkijs.DistributionPoint({
104
+ distributionPoint: [new pkijs.GeneralName({ type: 6, value: url })],
105
+ });
106
+ const cdp = new pkijs.CRLDistributionPoints({ distributionPoints: [dp] });
107
+ return new pkijs.Extension({
108
+ extnID: CRL_DISTRIBUTION_POINTS_OID,
109
+ critical: false,
110
+ extnValue: cdp.toSchema().toBER(),
111
+ });
112
+ }
113
+ /** Create an Authority Info Access extension with an OCSP URL */
114
+ export function makeOCSPAIAExt(url) {
115
+ const desc = new pkijs.AccessDescription({
116
+ accessMethod: OCSP_ACCESS_METHOD_OID,
117
+ accessLocation: new pkijs.GeneralName({ type: 6, value: url }),
118
+ });
119
+ const aia = new pkijs.InfoAccess({ accessDescriptions: [desc] });
120
+ return new pkijs.Extension({
121
+ extnID: AUTHORITY_INFO_ACCESS_OID,
122
+ critical: false,
123
+ extnValue: aia.toSchema().toBER(),
124
+ });
125
+ }
126
+ /** Create an Extended Key Usage extension */
127
+ export function makeExtKeyUsageExt(oids) {
128
+ const seq = new asn1js.Sequence({
129
+ value: oids.map((oid) => new asn1js.ObjectIdentifier({ value: oid })),
130
+ });
131
+ return new pkijs.Extension({
132
+ extnID: EXT_KEY_USAGE_OID,
133
+ critical: false,
134
+ extnValue: seq.toBER(),
135
+ });
136
+ }
137
+ export { OCSP_SIGNING_OID, CLIENT_AUTH_OID };
138
+ /** Create a signed X.509v2 CRL */
139
+ export async function createCRL(issuerCert, issuerKey, revokedSerials) {
140
+ const crl = new pkijs.CertificateRevocationList();
141
+ crl.version = 1; // CRLv2 = version field value 1
142
+ // Copy issuer from CA cert subject
143
+ crl.issuer = issuerCert.subject;
144
+ const now = new Date();
145
+ const next = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
146
+ crl.thisUpdate = new pkijs.Time({ type: 0, value: now });
147
+ crl.nextUpdate = new pkijs.Time({ type: 0, value: next });
148
+ if (revokedSerials.length > 0) {
149
+ crl.revokedCertificates = revokedSerials.map((serial) => new pkijs.RevokedCertificate({
150
+ userCertificate: new asn1js.Integer({ value: serial }),
151
+ revocationDate: new pkijs.Time({ type: 0, value: now }),
152
+ }));
153
+ }
154
+ await signWithEd25519(crl, issuerKey);
155
+ return crl;
156
+ }
157
+ /**
158
+ * Sign a pkijs BasicOCSPResponse with an Ed25519 key.
159
+ * Must be called after tbsResponseData.responses is populated.
160
+ */
161
+ export async function signBasicOCSPResponse(basicResponse, privateKey) {
162
+ const algId = new pkijs.AlgorithmIdentifier({ algorithmId: ED25519_OID });
163
+ basicResponse.signatureAlgorithm = algId;
164
+ // Encode the TBS response data
165
+ const tbsDer = basicResponse.tbsResponseData.toSchema(true).toBER();
166
+ basicResponse.tbsResponseData.tbsView = new Uint8Array(tbsDer);
167
+ const sig = await webcrypto.subtle.sign('Ed25519', privateKey, tbsDer);
168
+ basicResponse.signature = new asn1js.BitString({ valueHex: sig });
169
+ }
170
+ //# sourceMappingURL=certGenUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certGenUtils.js","sourceRoot":"","sources":["../../src/security/certGenUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Generate test certificates for CRL integration testing
3
+ *
4
+ * Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
5
+ */
6
+ export interface CrlCertificates {
7
+ /** Path to CA certificate */
8
+ ca: string;
9
+ /** Valid client certificate paths */
10
+ valid: {
11
+ /** Path to valid client certificate chain (cert + CA) */
12
+ cert: string;
13
+ /** Path to valid client private key */
14
+ key: string;
15
+ };
16
+ /** Revoked client certificate paths */
17
+ revoked: {
18
+ /** Path to revoked client certificate chain (cert + CA) */
19
+ cert: string;
20
+ /** Path to revoked client private key */
21
+ key: string;
22
+ };
23
+ /** Path to Certificate Revocation List */
24
+ crl: string;
25
+ }
26
+ /**
27
+ * Generate CRL test certificates using pure Node.js (no openssl CLI).
28
+ *
29
+ * Serial numbers:
30
+ * 1 = CA
31
+ * 2 = valid client
32
+ * 3 = revoked client
33
+ */
34
+ export declare function generateCrlCertificates(outputDir: string, crlHost: string, crlPort: number): Promise<CrlCertificates>;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Generate test certificates for CRL integration testing
3
+ *
4
+ * Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
5
+ */
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import { generateEd25519KeyPair, createCertificate, createCRL, makeCRLDistributionPointsExt, certToPem, crlToPem, CLIENT_AUTH_OID, makeExtKeyUsageExt, } from "../certGenUtils.js";
9
+ /**
10
+ * Generate CRL test certificates using pure Node.js (no openssl CLI).
11
+ *
12
+ * Serial numbers:
13
+ * 1 = CA
14
+ * 2 = valid client
15
+ * 3 = revoked client
16
+ */
17
+ export async function generateCrlCertificates(outputDir, crlHost, crlPort) {
18
+ const crlUrl = `http://${crlHost}:${crlPort}/test.crl`;
19
+ // --- CA ---
20
+ const caKey = await generateEd25519KeyPair();
21
+ const caKeyPath = path.join(outputDir, 'harper-ca.key');
22
+ fs.writeFileSync(caKeyPath, caKey.privateKeyPem);
23
+ const caCert = await createCertificate({
24
+ serialNumber: 1,
25
+ subject: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
26
+ issuer: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
27
+ validDays: 365,
28
+ issuerKey: caKey.privateKey,
29
+ subjectPublicKey: caKey.publicKey,
30
+ isCA: true,
31
+ });
32
+ const caCertPath = path.join(outputDir, 'harper-ca.crt');
33
+ fs.writeFileSync(caCertPath, certToPem(caCert));
34
+ // --- Valid client cert ---
35
+ const validKey = await generateEd25519KeyPair();
36
+ const validKeyPath = path.join(outputDir, 'client-valid.key');
37
+ fs.writeFileSync(validKeyPath, validKey.privateKeyPem);
38
+ const validCert = await createCertificate({
39
+ serialNumber: 2,
40
+ subject: { CN: 'Valid CRL Client', O: 'Harper CRL Test' },
41
+ issuer: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
42
+ validDays: 30,
43
+ issuerKey: caKey.privateKey,
44
+ subjectPublicKey: validKey.publicKey,
45
+ extensions: [makeCRLDistributionPointsExt(crlUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
46
+ });
47
+ const validCertPath = path.join(outputDir, 'client-valid.crt');
48
+ fs.writeFileSync(validCertPath, certToPem(validCert));
49
+ // Build chain: client cert + CA cert
50
+ const validChainPath = path.join(outputDir, 'client-valid-chain.crt');
51
+ fs.writeFileSync(validChainPath, certToPem(validCert) + certToPem(caCert));
52
+ // --- Revoked client cert ---
53
+ const revokedKey = await generateEd25519KeyPair();
54
+ const revokedKeyPath = path.join(outputDir, 'client-revoked.key');
55
+ fs.writeFileSync(revokedKeyPath, revokedKey.privateKeyPem);
56
+ const revokedCert = await createCertificate({
57
+ serialNumber: 3,
58
+ subject: { CN: 'Revoked CRL Client', O: 'Harper CRL Test' },
59
+ issuer: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
60
+ validDays: 30,
61
+ issuerKey: caKey.privateKey,
62
+ subjectPublicKey: revokedKey.publicKey,
63
+ extensions: [makeCRLDistributionPointsExt(crlUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
64
+ });
65
+ const revokedCertPath = path.join(outputDir, 'client-revoked.crt');
66
+ fs.writeFileSync(revokedCertPath, certToPem(revokedCert));
67
+ // Build chain: client cert + CA cert
68
+ const revokedChainPath = path.join(outputDir, 'client-revoked-chain.crt');
69
+ fs.writeFileSync(revokedChainPath, certToPem(revokedCert) + certToPem(caCert));
70
+ // --- CRL (serial 3 = revoked) ---
71
+ const crl = await createCRL(caCert, caKey.privateKey, [3]);
72
+ const crlPath = path.join(outputDir, 'test.crl');
73
+ fs.writeFileSync(crlPath, crlToPem(crl));
74
+ return {
75
+ ca: caCertPath,
76
+ valid: { cert: validChainPath, key: validKeyPath },
77
+ revoked: { cert: revokedChainPath, key: revokedKeyPath },
78
+ crl: crlPath,
79
+ };
80
+ }
81
+ //# sourceMappingURL=generate-test-certs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-test-certs.js","sourceRoot":"","sources":["../../../src/security/crl/generate-test-certs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Generate test certificates for OCSP integration testing
3
+ *
4
+ * Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
5
+ */
6
+ import * as pkijs from 'pkijs';
7
+ import { type Ed25519KeyPair } from '../certGenUtils.ts';
8
+ export interface OcspCertificates {
9
+ /** Path to CA certificate */
10
+ ca: string;
11
+ /** Valid client certificate paths */
12
+ valid: {
13
+ /** Path to valid client certificate chain (cert + CA) */
14
+ cert: string;
15
+ /** Path to valid client private key */
16
+ key: string;
17
+ };
18
+ /** Revoked client certificate paths */
19
+ revoked: {
20
+ /** Path to revoked client certificate chain (cert + CA) */
21
+ cert: string;
22
+ /** Path to revoked client private key */
23
+ key: string;
24
+ };
25
+ /** OCSP responder certificate paths */
26
+ ocsp: {
27
+ /** Path to OCSP responder certificate */
28
+ cert: string;
29
+ /** Path to OCSP responder private key */
30
+ key: string;
31
+ };
32
+ }
33
+ /** In-memory cert data needed by the OCSP server */
34
+ export interface OcspServerCerts {
35
+ caCert: pkijs.Certificate;
36
+ ocspKeyPair: Ed25519KeyPair;
37
+ ocspCert: pkijs.Certificate;
38
+ /** Maps decimal serial number string → status */
39
+ statusMap: Map<string, 'good' | 'revoked'>;
40
+ }
41
+ /**
42
+ * Generate OCSP test certificates using pure Node.js (no openssl CLI).
43
+ *
44
+ * Serial numbers:
45
+ * 1 = CA
46
+ * 2 = OCSP responder
47
+ * 3 = valid client
48
+ * 4 = revoked client
49
+ *
50
+ * Returns both file paths (for test code) and in-memory objects (for OCSP server).
51
+ */
52
+ export declare function generateOcspCertificates(outputDir: string, ocspHost: string, ocspPort: number): Promise<{
53
+ files: OcspCertificates;
54
+ serverCerts: OcspServerCerts;
55
+ }>;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Generate test certificates for OCSP integration testing
3
+ *
4
+ * Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
5
+ */
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import * as pkijs from 'pkijs';
9
+ import { generateEd25519KeyPair, createCertificate, makeOCSPAIAExt, makeExtKeyUsageExt, certToPem, OCSP_SIGNING_OID, CLIENT_AUTH_OID, } from "../certGenUtils.js";
10
+ /**
11
+ * Generate OCSP test certificates using pure Node.js (no openssl CLI).
12
+ *
13
+ * Serial numbers:
14
+ * 1 = CA
15
+ * 2 = OCSP responder
16
+ * 3 = valid client
17
+ * 4 = revoked client
18
+ *
19
+ * Returns both file paths (for test code) and in-memory objects (for OCSP server).
20
+ */
21
+ export async function generateOcspCertificates(outputDir, ocspHost, ocspPort) {
22
+ const ocspUrl = `http://${ocspHost}:${ocspPort}`;
23
+ // --- CA ---
24
+ const caKey = await generateEd25519KeyPair();
25
+ const caKeyPath = path.join(outputDir, 'harper-ca.key');
26
+ fs.writeFileSync(caKeyPath, caKey.privateKeyPem);
27
+ const caCert = await createCertificate({
28
+ serialNumber: 1,
29
+ subject: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
30
+ issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
31
+ validDays: 365,
32
+ issuerKey: caKey.privateKey,
33
+ subjectPublicKey: caKey.publicKey,
34
+ isCA: true,
35
+ });
36
+ const caCertPath = path.join(outputDir, 'harper-ca.crt');
37
+ fs.writeFileSync(caCertPath, certToPem(caCert));
38
+ // --- OCSP responder cert ---
39
+ const ocspKey = await generateEd25519KeyPair();
40
+ const ocspKeyPath = path.join(outputDir, 'ocsp.key');
41
+ fs.writeFileSync(ocspKeyPath, ocspKey.privateKeyPem);
42
+ const ocspCert = await createCertificate({
43
+ serialNumber: 2,
44
+ subject: { CN: 'OCSP Responder', O: 'Harper OCSP Test' },
45
+ issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
46
+ validDays: 365,
47
+ issuerKey: caKey.privateKey,
48
+ subjectPublicKey: ocspKey.publicKey,
49
+ extensions: [makeExtKeyUsageExt([OCSP_SIGNING_OID])],
50
+ });
51
+ const ocspCertPath = path.join(outputDir, 'ocsp.crt');
52
+ fs.writeFileSync(ocspCertPath, certToPem(ocspCert));
53
+ // --- Valid client cert ---
54
+ const validKey = await generateEd25519KeyPair();
55
+ const validKeyPath = path.join(outputDir, 'client-valid.key');
56
+ fs.writeFileSync(validKeyPath, validKey.privateKeyPem);
57
+ const validCert = await createCertificate({
58
+ serialNumber: 3,
59
+ subject: { CN: 'Valid Client', O: 'Harper OCSP Test' },
60
+ issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
61
+ validDays: 365,
62
+ issuerKey: caKey.privateKey,
63
+ subjectPublicKey: validKey.publicKey,
64
+ extensions: [makeOCSPAIAExt(ocspUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
65
+ });
66
+ const validCertPath = path.join(outputDir, 'client-valid.crt');
67
+ fs.writeFileSync(validCertPath, certToPem(validCert));
68
+ const validChainPath = path.join(outputDir, 'client-valid-chain.crt');
69
+ fs.writeFileSync(validChainPath, certToPem(validCert) + certToPem(caCert));
70
+ // --- Revoked client cert ---
71
+ const revokedKey = await generateEd25519KeyPair();
72
+ const revokedKeyPath = path.join(outputDir, 'client-revoked.key');
73
+ fs.writeFileSync(revokedKeyPath, revokedKey.privateKeyPem);
74
+ const revokedCert = await createCertificate({
75
+ serialNumber: 4,
76
+ subject: { CN: 'Revoked Client', O: 'Harper OCSP Test' },
77
+ issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
78
+ validDays: 365,
79
+ issuerKey: caKey.privateKey,
80
+ subjectPublicKey: revokedKey.publicKey,
81
+ extensions: [makeOCSPAIAExt(ocspUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
82
+ });
83
+ const revokedCertPath = path.join(outputDir, 'client-revoked.crt');
84
+ fs.writeFileSync(revokedCertPath, certToPem(revokedCert));
85
+ const revokedChainPath = path.join(outputDir, 'client-revoked-chain.crt');
86
+ fs.writeFileSync(revokedChainPath, certToPem(revokedCert) + certToPem(caCert));
87
+ const statusMap = new Map([
88
+ ['3', 'good'], // valid client serial
89
+ ['4', 'revoked'], // revoked client serial
90
+ ]);
91
+ return {
92
+ files: {
93
+ ca: caCertPath,
94
+ valid: { cert: validChainPath, key: validKeyPath },
95
+ revoked: { cert: revokedChainPath, key: revokedKeyPath },
96
+ ocsp: { cert: ocspCertPath, key: ocspKeyPath },
97
+ },
98
+ serverCerts: {
99
+ caCert,
100
+ ocspKeyPair: ocspKey,
101
+ ocspCert,
102
+ statusMap,
103
+ },
104
+ };
105
+ }
106
+ //# sourceMappingURL=generate-test-certs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-test-certs.js","sourceRoot":"","sources":["../../../src/security/ocsp/generate-test-certs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,eAAe,GAEf,MAAM,oBAAoB,CAAC;AAqC5B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,SAAiB,EACjB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,OAAO,GAAG,UAAU,QAAQ,IAAI,QAAQ,EAAE,CAAC;IAEjD,aAAa;IACb,MAAM,KAAK,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACxD,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACtC,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACxD,MAAM,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACvD,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,gBAAgB,EAAE,KAAK,CAAC,SAAS;QACjC,IAAI,EAAE,IAAI;KACV,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACzD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAEhD,8BAA8B;IAC9B,MAAM,OAAO,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACrD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC;QACxC,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACxD,MAAM,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACvD,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,gBAAgB,EAAE,OAAO,CAAC,SAAS;QACnC,UAAU,EAAE,CAAC,kBAAkB,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;KACpD,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACtD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEpD,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAChD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAC9D,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAEvD,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC;QACzC,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACtD,MAAM,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACvD,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,gBAAgB,EAAE,QAAQ,CAAC,SAAS;QACpC,UAAU,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;KAC5E,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAC/D,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;IAEtD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;IACtE,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3E,8BAA8B;IAC9B,MAAM,UAAU,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAClE,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC;IAE3D,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC;QAC3C,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACxD,MAAM,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE;QACvD,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,gBAAgB,EAAE,UAAU,CAAC,SAAS;QACtC,UAAU,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;KAC5E,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACnE,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;IAE1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,0BAA0B,CAAC,CAAC;IAC1E,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAE/E,MAAM,SAAS,GAAG,IAAI,GAAG,CAA6B;QACrD,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,sBAAsB;QACrC,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,wBAAwB;KAC1C,CAAC,CAAC;IAEH,OAAO;QACN,KAAK,EAAE;YACN,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,EAAE;YAClD,OAAO,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,cAAc,EAAE;YACxD,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,EAAE;SAC9C;QACD,WAAW,EAAE;YACZ,MAAM;YACN,WAAW,EAAE,OAAO;YACpB,QAAQ;YACR,SAAS;SACT;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Node.js OCSP (Online Certificate Status Protocol) responder
3
+ *
4
+ * A pure-Node.js replacement for `openssl ocsp`. Handles OCSP requests using pkijs
5
+ * for ASN.1 encoding and certGenUtils for Ed25519 signatures.
6
+ */
7
+ import { type Server } from 'node:http';
8
+ import type { OcspServerCerts } from './ocsp/generate-test-certs.ts';
9
+ /**
10
+ * Start a Node.js HTTP OCSP responder.
11
+ *
12
+ * @param port - Port to listen on
13
+ * @param certs - In-memory certificate and key data for the responder
14
+ * @returns Promise resolving to the HTTP server (already listening)
15
+ */
16
+ export declare function startOcspServer(port: number, certs: OcspServerCerts): Promise<Server>;
17
+ /** Stop a running OCSP server */
18
+ export declare function stopOcspServer(server: Server): Promise<void>;