self-sign 5.6.7

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.

Potentially problematic release.


This version of self-sign might be problematic. Click here for more details.

@@ -0,0 +1,242 @@
1
+ var { assert } = require('chai');
2
+ var crypto = require('crypto');
3
+
4
+ describe('CA signing', function () {
5
+ var generate = require('../index').generate;
6
+
7
+ it('should generate certificate signed by provided CA', async function () {
8
+ // First generate a self-signed CA certificate
9
+ const ca = await generate([
10
+ { name: 'commonName', value: 'Test CA' },
11
+ { name: 'organizationName', value: 'Test Organization' }
12
+ ], {
13
+ algorithm: 'sha256'
14
+ },null);
15
+
16
+ // Generate a certificate signed by the CA
17
+ const pems = await generate([
18
+ { name: 'commonName', value: 'localhost' }
19
+ ], {
20
+ algorithm: 'sha256',
21
+ ca: {
22
+ key: ca.private,
23
+ cert: ca.cert
24
+ }
25
+ },null);
26
+
27
+ assert.ok(!!pems.private, 'has a private key');
28
+ assert.ok(!!pems.public, 'has a public key');
29
+ assert.ok(!!pems.cert, 'has a certificate');
30
+ assert.ok(!!pems.fingerprint, 'has fingerprint');
31
+
32
+ const cert = new crypto.X509Certificate(pems.cert);
33
+ const caCert = new crypto.X509Certificate(ca.cert);
34
+
35
+ // Verify issuer is the CA, not self-signed
36
+ assert.include(cert.issuer, 'CN=Test CA', 'issuer should be the CA');
37
+ assert.include(cert.subject, 'CN=localhost', 'subject should be localhost');
38
+ assert.notEqual(cert.issuer, cert.subject, 'should not be self-signed');
39
+
40
+ // Verify the certificate is signed by the CA
41
+ assert.isTrue(cert.verify(caCert.publicKey), 'certificate should be verified by CA public key');
42
+ });
43
+
44
+ it('should include Subject Alternative Name extension', async function () {
45
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
46
+ algorithm: 'sha256'
47
+ },null);
48
+
49
+ const pems = await generate([
50
+ { name: 'commonName', value: 'example.com' }
51
+ ], {
52
+ algorithm: 'sha256',
53
+ ca: { key: ca.private, cert: ca.cert }
54
+ },null);
55
+
56
+ const cert = new crypto.X509Certificate(pems.cert);
57
+ assert.include(cert.subjectAltName, 'DNS:example.com', 'should have DNS SAN matching CN');
58
+ });
59
+
60
+ it('should include IP SAN for localhost', async function () {
61
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
62
+ algorithm: 'sha256'
63
+ },null);
64
+
65
+ const pems = await generate([
66
+ { name: 'commonName', value: 'localhost' }
67
+ ], {
68
+ algorithm: 'sha256',
69
+ ca: { key: ca.private, cert: ca.cert }
70
+ },null);
71
+
72
+ const cert = new crypto.X509Certificate(pems.cert);
73
+ assert.include(cert.subjectAltName, 'DNS:localhost', 'should have DNS SAN');
74
+ assert.include(cert.subjectAltName, 'IP Address:127.0.0.1', 'should have IP SAN for localhost');
75
+ });
76
+
77
+ it('should support different hash algorithms with CA signing', async function () {
78
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
79
+ algorithm: 'sha256'
80
+ },null);
81
+
82
+ // Test sha384
83
+ const pems384 = await generate([{ name: 'commonName', value: 'test384.local' }], {
84
+ algorithm: 'sha384',
85
+ ca: { key: ca.private, cert: ca.cert }
86
+ },null);
87
+
88
+ const cert384 = new crypto.X509Certificate(pems384.cert);
89
+ assert.ok(cert384.publicKey, 'should generate sha384 CA-signed cert');
90
+
91
+ // Test sha512
92
+ const pems512 = await generate([{ name: 'commonName', value: 'test512.local' }], {
93
+ algorithm: 'sha512',
94
+ ca: { key: ca.private, cert: ca.cert }
95
+ },null);
96
+
97
+ const cert512 = new crypto.X509Certificate(pems512.cert);
98
+ assert.ok(cert512.publicKey, 'should generate sha512 CA-signed cert');
99
+ });
100
+
101
+ it('should respect notAfterDate option with CA signing', async function () {
102
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
103
+ algorithm: 'sha256'
104
+ },null);
105
+
106
+ const notBefore = new Date('2025-01-01T00:00:00Z');
107
+ const notAfter = new Date('2025-01-31T00:00:00Z'); // 30 days validity
108
+ const pems = await generate([{ name: 'commonName', value: 'short-lived.local' }], {
109
+ algorithm: 'sha256',
110
+ notBeforeDate: notBefore,
111
+ notAfterDate: notAfter,
112
+ ca: { key: ca.private, cert: ca.cert }
113
+ });
114
+
115
+ const cert = new crypto.X509Certificate(pems.cert);
116
+ const validFrom = new Date(cert.validFrom);
117
+ const validTo = new Date(cert.validTo);
118
+
119
+ assert.approximately(validFrom.getTime(), notBefore.getTime(), 5000, 'should use custom notBeforeDate');
120
+ assert.approximately(validTo.getTime(), notAfter.getTime(), 5000, 'should use custom notAfterDate');
121
+ });
122
+
123
+ it('should generate unique certificates with same CA', async function () {
124
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
125
+ algorithm: 'sha256'
126
+ });
127
+
128
+ const pems1 = await generate([{ name: 'commonName', value: 'test1.local' }], {
129
+ algorithm: 'sha256',
130
+ ca: { key: ca.private, cert: ca.cert }
131
+ });
132
+
133
+ const pems2 = await generate([{ name: 'commonName', value: 'test2.local' }], {
134
+ algorithm: 'sha256',
135
+ ca: { key: ca.private, cert: ca.cert }
136
+ });
137
+
138
+ const cert1 = new crypto.X509Certificate(pems1.cert);
139
+ const cert2 = new crypto.X509Certificate(pems2.cert);
140
+
141
+ assert.notEqual(cert1.serialNumber, cert2.serialNumber, 'serial numbers should be unique');
142
+ assert.notEqual(pems1.private, pems2.private, 'private keys should be different');
143
+ });
144
+
145
+ it('should work with custom keySize and CA signing', async function () {
146
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
147
+ algorithm: 'sha256',
148
+ keySize: 4096
149
+ });
150
+
151
+ const pems = await generate([{ name: 'commonName', value: 'bigkey.local' }], {
152
+ algorithm: 'sha256',
153
+ keySize: 4096,
154
+ ca: { key: ca.private, cert: ca.cert }
155
+ });
156
+
157
+ const privateKey = crypto.createPrivateKey(pems.private);
158
+ assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 4096, 'should use custom key size');
159
+
160
+ const cert = new crypto.X509Certificate(pems.cert);
161
+ const caCert = new crypto.X509Certificate(ca.cert);
162
+ assert.isTrue(cert.verify(caCert.publicKey), 'certificate should verify with CA');
163
+ });
164
+
165
+ it('should support existing keyPair with CA signing', async function () {
166
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
167
+ algorithm: 'sha256'
168
+ });
169
+
170
+ // Generate a key pair first
171
+ const keyPair = await generate([{ name: 'commonName', value: 'keypair.local' }], {
172
+ algorithm: 'sha256'
173
+ });
174
+
175
+ // Use existing key pair with CA signing
176
+ const pems = await generate([{ name: 'commonName', value: 'reused.local' }], {
177
+ algorithm: 'sha256',
178
+ keyPair: {
179
+ privateKey: keyPair.private,
180
+ publicKey: keyPair.public
181
+ },
182
+ ca: { key: ca.private, cert: ca.cert }
183
+ });
184
+
185
+ assert.strictEqual(pems.private, keyPair.private, 'should use provided private key');
186
+ assert.strictEqual(pems.public, keyPair.public, 'should use provided public key');
187
+
188
+ const cert = new crypto.X509Certificate(pems.cert);
189
+ const caCert = new crypto.X509Certificate(ca.cert);
190
+ assert.isTrue(cert.verify(caCert.publicKey), 'certificate should verify with CA');
191
+ });
192
+
193
+ it('should include proper extended key usage extensions', async function () {
194
+ const ca = await generate([{ name: 'commonName', value: 'Test CA' }], {
195
+ algorithm: 'sha256'
196
+ });
197
+
198
+ const pems = await generate([{ name: 'commonName', value: 'server.local' }], {
199
+ algorithm: 'sha256',
200
+ ca: { key: ca.private, cert: ca.cert }
201
+ });
202
+
203
+ const cert = new crypto.X509Certificate(pems.cert);
204
+
205
+ // Check extended key usage (OIDs)
206
+ // 1.3.6.1.5.5.7.3.1 = serverAuth
207
+ // 1.3.6.1.5.5.7.3.2 = clientAuth
208
+ assert.include(cert.keyUsage, '1.3.6.1.5.5.7.3.1', 'should have serverAuth extended key usage');
209
+ assert.include(cert.keyUsage, '1.3.6.1.5.5.7.3.2', 'should have clientAuth extended key usage');
210
+ });
211
+
212
+ it('should work with PKCS#1 RSA key format', async function () {
213
+ // Generate a CA with PKCS#1 format key (like mkcert uses)
214
+ const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
215
+ modulusLength: 2048,
216
+ privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
217
+ publicKeyEncoding: { type: 'spki', format: 'pem' }
218
+ });
219
+
220
+ // Create a self-signed CA cert using the PKCS#1 key
221
+ const ca = await generate([{ name: 'commonName', value: 'PKCS1 CA' }], {
222
+ algorithm: 'sha256'
223
+ });
224
+
225
+ // Now test that we can use a PKCS#1 formatted key as CA
226
+ // Convert our generated key to PKCS#1 for testing
227
+ const caKeyObject = crypto.createPrivateKey(ca.private);
228
+ const pkcs1Key = caKeyObject.export({ type: 'pkcs1', format: 'pem' });
229
+
230
+ const pems = await generate([{ name: 'commonName', value: 'pkcs1-test.local' }], {
231
+ algorithm: 'sha256',
232
+ ca: {
233
+ key: pkcs1Key,
234
+ cert: ca.cert
235
+ }
236
+ });
237
+
238
+ const cert = new crypto.X509Certificate(pems.cert);
239
+ const caCert = new crypto.X509Certificate(ca.cert);
240
+ assert.isTrue(cert.verify(caCert.publicKey), 'should work with PKCS#1 key format');
241
+ });
242
+ });
@@ -0,0 +1,142 @@
1
+ var { assert } = require('chai');
2
+ var crypto = require('crypto');
3
+
4
+ describe('EC keys', function () {
5
+ var generate = require('../index').generate;
6
+
7
+ it('should generate EC certificate with P-256 curve (default)', async function () {
8
+ var pems = await generate(null, { keyType: 'ec' },null);
9
+
10
+ assert.ok(!!pems.private, 'has a private key');
11
+ assert.ok(!!pems.public, 'has a public key');
12
+ assert.ok(!!pems.cert, 'has a certificate');
13
+ assert.ok(!!pems.fingerprint, 'has fingerprint');
14
+
15
+ const privateKey = crypto.createPrivateKey(pems.private);
16
+ assert.strictEqual(privateKey.asymmetricKeyType, 'ec', 'should be EC key');
17
+ assert.strictEqual(privateKey.asymmetricKeyDetails.namedCurve, 'prime256v1', 'should use P-256 curve');
18
+
19
+ const cert = new crypto.X509Certificate(pems.cert);
20
+ assert.ok(cert.subject, 'cert has a subject');
21
+ });
22
+
23
+ it('should generate EC certificate with P-384 curve', async function () {
24
+ var pems = await generate(null, { keyType: 'ec', curve: 'P-384' },null);
25
+
26
+ const privateKey = crypto.createPrivateKey(pems.private);
27
+ assert.strictEqual(privateKey.asymmetricKeyType, 'ec', 'should be EC key');
28
+ assert.strictEqual(privateKey.asymmetricKeyDetails.namedCurve, 'secp384r1', 'should use P-384 curve');
29
+
30
+ const cert = new crypto.X509Certificate(pems.cert);
31
+ assert.ok(cert.publicKey, 'can generate P-384 EC certs');
32
+ });
33
+
34
+ it('should generate EC certificate with P-521 curve', async function () {
35
+ var pems = await generate(null, { keyType: 'ec', curve: 'P-521' },null);
36
+
37
+ const privateKey = crypto.createPrivateKey(pems.private);
38
+ assert.strictEqual(privateKey.asymmetricKeyType, 'ec', 'should be EC key');
39
+ assert.strictEqual(privateKey.asymmetricKeyDetails.namedCurve, 'secp521r1', 'should use P-521 curve');
40
+
41
+ const cert = new crypto.X509Certificate(pems.cert);
42
+ assert.ok(cert.publicKey, 'can generate P-521 EC certs');
43
+ });
44
+
45
+ it('should generate valid EC key pair that work together', async function () {
46
+ var pems = await generate(null, { keyType: 'ec', curve: 'P-256' },null);
47
+
48
+ const testData = 'Hello, World!';
49
+
50
+ const privateKey = crypto.createPrivateKey(pems.private);
51
+ const publicKey = crypto.createPublicKey(pems.public);
52
+
53
+ // Sign with private key
54
+ const sign = crypto.createSign('SHA256');
55
+ sign.update(testData);
56
+ sign.end();
57
+ const signature = sign.sign(privateKey);
58
+
59
+ // Verify with public key
60
+ const verify = crypto.createVerify('SHA256');
61
+ verify.update(testData);
62
+ verify.end();
63
+ const isValid = verify.verify(publicKey, signature);
64
+
65
+ assert.isTrue(isValid, 'EC public key should verify signature from EC private key');
66
+ });
67
+
68
+ it('should support EC with sha256 algorithm', async function () {
69
+ var pems = await generate(null, { keyType: 'ec', algorithm: 'sha256' },null);
70
+
71
+ const cert = new crypto.X509Certificate(pems.cert);
72
+ assert.ok(cert.publicKey, 'can generate EC cert with sha256');
73
+ });
74
+
75
+ it('should support EC with sha384 algorithm', async function () {
76
+ var pems = await generate(null, { keyType: 'ec', curve: 'P-384', algorithm: 'sha384' },null);
77
+
78
+ const cert = new crypto.X509Certificate(pems.cert);
79
+ assert.ok(cert.publicKey, 'can generate EC cert with sha384');
80
+ });
81
+
82
+ it('should support EC with sha512 algorithm', async function () {
83
+ var pems = await generate(null, { keyType: 'ec', curve: 'P-521', algorithm: 'sha512' },null);
84
+
85
+ const cert = new crypto.X509Certificate(pems.cert);
86
+ assert.ok(cert.publicKey, 'can generate EC cert with sha512');
87
+ });
88
+
89
+ it('should generate EC client certificate', async function () {
90
+ var pems = await generate(null, { keyType: 'ec', clientCertificate: true },null);
91
+
92
+ assert.ok(!!pems.clientcert, 'should include a client cert');
93
+ assert.ok(!!pems.clientprivate, 'should include a client private key');
94
+ assert.ok(!!pems.clientpublic, 'should include a client public key');
95
+
96
+ const clientPrivateKey = crypto.createPrivateKey(pems.clientprivate);
97
+ assert.strictEqual(clientPrivateKey.asymmetricKeyType, 'ec', 'client key should be EC');
98
+ });
99
+
100
+ it('should support passphrase with EC keys', async function () {
101
+ const passphrase = 'ec-secret-passphrase';
102
+ var pems = await generate(null, { keyType: 'ec', passphrase: passphrase },null);
103
+
104
+ assert.include(pems.private, 'ENCRYPTED', 'EC private key should be encrypted');
105
+
106
+ const privateKey = crypto.createPrivateKey({
107
+ key: pems.private,
108
+ passphrase: passphrase
109
+ });
110
+ assert.strictEqual(privateKey.asymmetricKeyType, 'ec', 'decrypted key should be EC');
111
+ });
112
+
113
+ it('should support using existing EC keyPair', async function () {
114
+ const firstPems = await generate(null, { keyType: 'ec', curve: 'P-256' },null);
115
+
116
+ const secondPems = await generate(null, {
117
+ keyType: 'ec',
118
+ curve: 'P-256',
119
+ keyPair: {
120
+ privateKey: firstPems.private,
121
+ publicKey: firstPems.public
122
+ }
123
+ },null);
124
+
125
+ assert.strictEqual(firstPems.private, secondPems.private, 'should use provided EC private key');
126
+ assert.strictEqual(firstPems.public, secondPems.public, 'should use provided EC public key');
127
+ });
128
+
129
+ it('should support custom attributes with EC', async function () {
130
+ const attrs = [
131
+ { name: 'commonName', value: 'ec-test.example.com' },
132
+ { name: 'countryName', value: 'US' },
133
+ { name: 'organizationName', value: 'EC Test Corp' }
134
+ ];
135
+
136
+ var pems = await generate(attrs, { keyType: 'ec' },null);
137
+ const cert = new crypto.X509Certificate(pems.cert);
138
+
139
+ assert.include(cert.subject, 'CN=ec-test.example.com', 'should include custom CN');
140
+ assert.include(cert.subject, 'O=EC Test Corp', 'should include custom organization');
141
+ });
142
+ });