source: trip-planner-front/node_modules/selfsigned/index.js@ 188ee53

Last change on this file since 188ee53 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.3 KB
Line 
1var forge = require('node-forge');
2
3// a hexString is considered negative if it's most significant bit is 1
4// because serial numbers use ones' complement notation
5// this RFC in section 4.1.2.2 requires serial numbers to be positive
6// http://www.ietf.org/rfc/rfc5280.txt
7function toPositiveHex(hexString){
8 var mostSiginficativeHexAsInt = parseInt(hexString[0], 16);
9 if (mostSiginficativeHexAsInt < 8){
10 return hexString;
11 }
12
13 mostSiginficativeHexAsInt -= 8;
14 return mostSiginficativeHexAsInt.toString() + hexString.substring(1);
15}
16
17function getAlgorithm(key) {
18 switch (key) {
19 case 'sha256':
20 return forge.md.sha256.create();
21 default:
22 return forge.md.sha1.create();
23 }
24}
25
26/**
27 *
28 * @param {forge.pki.CertificateField[]} attrs Attributes used for subject and issuer.
29 * @param {object} options
30 * @param {number} [options.days=365] the number of days before expiration
31 * @param {number} [options.keySize=1024] the size for the private key in bits
32 * @param {object} [options.extensions] additional extensions for the certificate
33 * @param {string} [options.algorithm="sha1"] The signature algorithm sha256 or sha1
34 * @param {boolean} [options.pkcs7=false] include PKCS#7 as part of the output
35 * @param {boolean} [options.clientCertificate=false] generate client cert signed by the original key
36 * @param {string} [options.clientCertificateCN="John Doe jdoe123"] client certificate's common name
37 * @param {function} [done] Optional callback, if not provided the generation is synchronous
38 * @returns
39 */
40exports.generate = function generate(attrs, options, done) {
41 if (typeof attrs === 'function') {
42 done = attrs;
43 attrs = undefined;
44 } else if (typeof options === 'function') {
45 done = options;
46 options = {};
47 }
48
49 options = options || {};
50
51 var generatePem = function (keyPair) {
52 var cert = forge.pki.createCertificate();
53
54 cert.serialNumber = toPositiveHex(forge.util.bytesToHex(forge.random.getBytesSync(9))); // the serial number can be decimal or hex (if preceded by 0x)
55
56 cert.validity.notBefore = new Date();
57 cert.validity.notAfter = new Date();
58 cert.validity.notAfter.setDate(cert.validity.notBefore.getDate() + (options.days || 365));
59
60 attrs = attrs || [{
61 name: 'commonName',
62 value: 'example.org'
63 }, {
64 name: 'countryName',
65 value: 'US'
66 }, {
67 shortName: 'ST',
68 value: 'Virginia'
69 }, {
70 name: 'localityName',
71 value: 'Blacksburg'
72 }, {
73 name: 'organizationName',
74 value: 'Test'
75 }, {
76 shortName: 'OU',
77 value: 'Test'
78 }];
79
80 cert.setSubject(attrs);
81 cert.setIssuer(attrs);
82
83 cert.publicKey = keyPair.publicKey;
84
85 cert.setExtensions(options.extensions || [{
86 name: 'basicConstraints',
87 cA: true
88 }, {
89 name: 'keyUsage',
90 keyCertSign: true,
91 digitalSignature: true,
92 nonRepudiation: true,
93 keyEncipherment: true,
94 dataEncipherment: true
95 }, {
96 name: 'subjectAltName',
97 altNames: [{
98 type: 6, // URI
99 value: 'http://example.org/webid#me'
100 }]
101 }]);
102
103 cert.sign(keyPair.privateKey, getAlgorithm(options && options.algorithm));
104
105 const fingerprint = forge.md.sha1
106 .create()
107 .update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes())
108 .digest()
109 .toHex()
110 .match(/.{2}/g)
111 .join(':');
112
113 var pem = {
114 private: forge.pki.privateKeyToPem(keyPair.privateKey),
115 public: forge.pki.publicKeyToPem(keyPair.publicKey),
116 cert: forge.pki.certificateToPem(cert),
117 fingerprint: fingerprint,
118 };
119
120 if (options && options.pkcs7) {
121 var p7 = forge.pkcs7.createSignedData();
122 p7.addCertificate(cert);
123 pem.pkcs7 = forge.pkcs7.messageToPem(p7);
124 }
125
126 if (options && options.clientCertificate) {
127 var clientkeys = forge.pki.rsa.generateKeyPair(1024);
128 var clientcert = forge.pki.createCertificate();
129 clientcert.serialNumber = toPositiveHex(forge.util.bytesToHex(forge.random.getBytesSync(9)));
130 clientcert.validity.notBefore = new Date();
131 clientcert.validity.notAfter = new Date();
132 clientcert.validity.notAfter.setFullYear(clientcert.validity.notBefore.getFullYear() + 1);
133
134 var clientAttrs = JSON.parse(JSON.stringify(attrs));
135
136 for(var i = 0; i < clientAttrs.length; i++) {
137 if(clientAttrs[i].name === 'commonName') {
138 if( options.clientCertificateCN )
139 clientAttrs[i] = { name: 'commonName', value: options.clientCertificateCN };
140 else
141 clientAttrs[i] = { name: 'commonName', value: 'John Doe jdoe123' };
142 }
143 }
144
145 clientcert.setSubject(clientAttrs);
146
147 // Set the issuer to the parent key
148 clientcert.setIssuer(attrs);
149
150 clientcert.publicKey = clientkeys.publicKey;
151
152 // Sign client cert with root cert
153 clientcert.sign(keyPair.privateKey);
154
155 pem.clientprivate = forge.pki.privateKeyToPem(clientkeys.privateKey);
156 pem.clientpublic = forge.pki.publicKeyToPem(clientkeys.publicKey);
157 pem.clientcert = forge.pki.certificateToPem(clientcert);
158
159 if (options.pkcs7) {
160 var clientp7 = forge.pkcs7.createSignedData();
161 clientp7.addCertificate(clientcert);
162 pem.clientpkcs7 = forge.pkcs7.messageToPem(clientp7);
163 }
164 }
165
166 var caStore = forge.pki.createCaStore();
167 caStore.addCertificate(cert);
168
169 try {
170 forge.pki.verifyCertificateChain(caStore, [cert],
171 function (vfd, depth, chain) {
172 if (vfd !== true) {
173 throw new Error('Certificate could not be verified.');
174 }
175 return true;
176 });
177 }
178 catch(ex) {
179 throw new Error(ex);
180 }
181
182 return pem;
183 };
184
185 var keySize = options.keySize || 1024;
186
187 if (done) { // async scenario
188 return forge.pki.rsa.generateKeyPair({ bits: keySize }, function (err, keyPair) {
189 if (err) { return done(err); }
190
191 try {
192 return done(null, generatePem(keyPair));
193 } catch (ex) {
194 return done(ex);
195 }
196 });
197 }
198
199 var keyPair = options.keyPair ? {
200 privateKey: forge.pki.privateKeyFromPem(options.keyPair.privateKey),
201 publicKey: forge.pki.publicKeyFromPem(options.keyPair.publicKey)
202 } : forge.pki.rsa.generateKeyPair(keySize);
203
204 return generatePem(keyPair);
205};
Note: See TracBrowser for help on using the repository browser.