]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / node_modules / request / node_modules / http-signature / node_modules / sshpk / lib / formats / x509.js
1 // Copyright 2016 Joyent, Inc.
2
3 module.exports = {
4         read: read,
5         verify: verify,
6         sign: sign,
7         write: write
8 };
9
10 var assert = require('assert-plus');
11 var asn1 = require('asn1');
12 var algs = require('../algs');
13 var utils = require('../utils');
14 var Key = require('../key');
15 var PrivateKey = require('../private-key');
16 var pem = require('./pem');
17 var Identity = require('../identity');
18 var Signature = require('../signature');
19 var Certificate = require('../certificate');
20 var pkcs8 = require('./pkcs8');
21
22 /*
23  * This file is based on RFC5280 (X.509).
24  */
25
26 /* Helper to read in a single mpint */
27 function readMPInt(der, nm) {
28         assert.strictEqual(der.peek(), asn1.Ber.Integer,
29             nm + ' is not an Integer');
30         return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
31 }
32
33 function verify(cert, key) {
34         var sig = cert.signatures.x509;
35         assert.object(sig, 'x509 signature');
36
37         var algParts = sig.algo.split('-');
38         if (algParts[0] !== key.type)
39                 return (false);
40
41         var blob = sig.cache;
42         if (blob === undefined) {
43                 var der = new asn1.BerWriter();
44                 writeTBSCert(cert, der);
45                 blob = der.buffer;
46         }
47
48         var verifier = key.createVerify(algParts[1]);
49         verifier.write(blob);
50         return (verifier.verify(sig.signature));
51 }
52
53 function Local(i) {
54         return (asn1.Ber.Context | asn1.Ber.Constructor | i);
55 }
56
57 function Context(i) {
58         return (asn1.Ber.Context | i);
59 }
60
61 var SIGN_ALGS = {
62         'rsa-md5': '1.2.840.113549.1.1.4',
63         'rsa-sha1': '1.2.840.113549.1.1.5',
64         'rsa-sha256': '1.2.840.113549.1.1.11',
65         'rsa-sha384': '1.2.840.113549.1.1.12',
66         'rsa-sha512': '1.2.840.113549.1.1.13',
67         'dsa-sha1': '1.2.840.10040.4.3',
68         'dsa-sha256': '2.16.840.1.101.3.4.3.2',
69         'ecdsa-sha1': '1.2.840.10045.4.1',
70         'ecdsa-sha256': '1.2.840.10045.4.3.2',
71         'ecdsa-sha384': '1.2.840.10045.4.3.3',
72         'ecdsa-sha512': '1.2.840.10045.4.3.4'
73 };
74 Object.keys(SIGN_ALGS).forEach(function (k) {
75         SIGN_ALGS[SIGN_ALGS[k]] = k;
76 });
77 SIGN_ALGS['1.3.14.3.2.3'] = 'rsa-md5';
78 SIGN_ALGS['1.3.14.3.2.29'] = 'rsa-sha1';
79
80 var EXTS = {
81         'issuerKeyId': '2.5.29.35',
82         'altName': '2.5.29.17'
83 };
84
85 function read(buf, options) {
86         if (typeof (buf) === 'string') {
87                 buf = new Buffer(buf, 'binary');
88         }
89         assert.buffer(buf, 'buf');
90
91         var der = new asn1.BerReader(buf);
92
93         der.readSequence();
94         if (Math.abs(der.length - der.remain) > 1) {
95                 throw (new Error('DER sequence does not contain whole byte ' +
96                     'stream'));
97         }
98
99         var tbsStart = der.offset;
100         der.readSequence();
101         var sigOffset = der.offset + der.length;
102         var tbsEnd = sigOffset;
103
104         if (der.peek() === Local(0)) {
105                 der.readSequence(Local(0));
106                 var version = der.readInt();
107                 assert.ok(version <= 3,
108                     'only x.509 versions up to v3 supported');
109         }
110
111         var cert = {};
112         cert.signatures = {};
113         var sig = (cert.signatures.x509 = {});
114         sig.extras = {};
115
116         cert.serial = readMPInt(der, 'serial');
117
118         der.readSequence();
119         var after = der.offset + der.length;
120         var certAlgOid = der.readOID();
121         var certAlg = SIGN_ALGS[certAlgOid];
122         if (certAlg === undefined)
123                 throw (new Error('unknown signature algorithm ' + certAlgOid));
124
125         der._offset = after;
126         cert.issuer = Identity.parseAsn1(der);
127
128         der.readSequence();
129         cert.validFrom = readDate(der);
130         cert.validUntil = readDate(der);
131
132         cert.subjects = [Identity.parseAsn1(der)];
133
134         der.readSequence();
135         after = der.offset + der.length;
136         cert.subjectKey = pkcs8.readPkcs8(undefined, 'public', der);
137         der._offset = after;
138
139         /* issuerUniqueID */
140         if (der.peek() === Local(1)) {
141                 der.readSequence(Local(1));
142                 sig.extras.issuerUniqueID =
143                     buf.slice(der.offset, der.offset + der.length);
144                 der._offset += der.length;
145         }
146
147         /* subjectUniqueID */
148         if (der.peek() === Local(2)) {
149                 der.readSequence(Local(2));
150                 sig.extras.subjectUniqueID =
151                     buf.slice(der.offset, der.offset + der.length);
152                 der._offset += der.length;
153         }
154
155         /* extensions */
156         if (der.peek() === Local(3)) {
157                 der.readSequence(Local(3));
158                 var extEnd = der.offset + der.length;
159                 der.readSequence();
160
161                 while (der.offset < extEnd)
162                         readExtension(cert, buf, der);
163
164                 assert.strictEqual(der.offset, extEnd);
165         }
166
167         assert.strictEqual(der.offset, sigOffset);
168
169         der.readSequence();
170         after = der.offset + der.length;
171         var sigAlgOid = der.readOID();
172         var sigAlg = SIGN_ALGS[sigAlgOid];
173         if (sigAlg === undefined)
174                 throw (new Error('unknown signature algorithm ' + sigAlgOid));
175         der._offset = after;
176
177         var sigData = der.readString(asn1.Ber.BitString, true);
178         if (sigData[0] === 0)
179                 sigData = sigData.slice(1);
180         var algParts = sigAlg.split('-');
181
182         sig.signature = Signature.parse(sigData, algParts[0], 'asn1');
183         sig.signature.hashAlgorithm = algParts[1];
184         sig.algo = sigAlg;
185         sig.cache = buf.slice(tbsStart, tbsEnd);
186
187         return (new Certificate(cert));
188 }
189
190 function readDate(der) {
191         if (der.peek() === asn1.Ber.UTCTime) {
192                 return (utcTimeToDate(der.readString(asn1.Ber.UTCTime)));
193         } else if (der.peek() === asn1.Ber.GeneralizedTime) {
194                 return (gTimeToDate(der.readString(asn1.Ber.GeneralizedTime)));
195         } else {
196                 throw (new Error('Unsupported date format'));
197         }
198 }
199
200 /* RFC5280, section 4.2.1.6 (GeneralName type) */
201 var ALTNAME = {
202         OtherName: Local(0),
203         RFC822Name: Context(1),
204         DNSName: Context(2),
205         X400Address: Local(3),
206         DirectoryName: Local(4),
207         EDIPartyName: Local(5),
208         URI: Context(6),
209         IPAddress: Context(7),
210         OID: Context(8)
211 };
212
213 function readExtension(cert, buf, der) {
214         der.readSequence();
215         var after = der.offset + der.length;
216         var extId = der.readOID();
217         var id;
218         var sig = cert.signatures.x509;
219         sig.extras.exts = [];
220
221         var critical;
222         if (der.peek() === asn1.Ber.Boolean)
223                 critical = der.readBoolean();
224
225         switch (extId) {
226         case (EXTS.altName):
227                 der.readSequence(asn1.Ber.OctetString);
228                 der.readSequence();
229                 var aeEnd = der.offset + der.length;
230                 while (der.offset < aeEnd) {
231                         switch (der.peek()) {
232                         case ALTNAME.OtherName:
233                         case ALTNAME.EDIPartyName:
234                                 der.readSequence();
235                                 der._offset += der.length;
236                                 break;
237                         case ALTNAME.OID:
238                                 der.readOID(ALTNAME.OID);
239                                 break;
240                         case ALTNAME.RFC822Name:
241                                 /* RFC822 specifies email addresses */
242                                 var email = der.readString(ALTNAME.RFC822Name);
243                                 id = Identity.forEmail(email);
244                                 if (!cert.subjects[0].equals(id))
245                                         cert.subjects.push(id);
246                                 break;
247                         case ALTNAME.DirectoryName:
248                                 der.readSequence(ALTNAME.DirectoryName);
249                                 id = Identity.parseAsn1(der);
250                                 if (!cert.subjects[0].equals(id))
251                                         cert.subjects.push(id);
252                                 break;
253                         case ALTNAME.DNSName:
254                                 var host = der.readString(
255                                     ALTNAME.DNSName);
256                                 id = Identity.forHost(host);
257                                 if (!cert.subjects[0].equals(id))
258                                         cert.subjects.push(id);
259                                 break;
260                         default:
261                                 der.readString(der.peek());
262                                 break;
263                         }
264                 }
265                 sig.extras.exts.push({ oid: extId, critical: critical });
266                 break;
267         default:
268                 sig.extras.exts.push({
269                         oid: extId,
270                         critical: critical,
271                         data: der.readString(asn1.Ber.OctetString, true)
272                 });
273                 break;
274         }
275
276         der._offset = after;
277 }
278
279 var UTCTIME_RE =
280     /^([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?Z$/;
281 function utcTimeToDate(t) {
282         var m = t.match(UTCTIME_RE);
283         assert.ok(m, 'timestamps must be in UTC');
284         var d = new Date();
285
286         var thisYear = d.getUTCFullYear();
287         var century = Math.floor(thisYear / 100) * 100;
288
289         var year = parseInt(m[1], 10);
290         if (thisYear % 100 < 50 && year >= 60)
291                 year += (century - 1);
292         else
293                 year += century;
294         d.setUTCFullYear(year, parseInt(m[2], 10) - 1, parseInt(m[3], 10));
295         d.setUTCHours(parseInt(m[4], 10), parseInt(m[5], 10));
296         if (m[6] && m[6].length > 0)
297                 d.setUTCSeconds(parseInt(m[6], 10));
298         return (d);
299 }
300
301 var GTIME_RE =
302     /^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?Z$/;
303 function gTimeToDate(t) {
304         var m = t.match(GTIME_RE);
305         assert.ok(m);
306         var d = new Date();
307
308         d.setUTCFullYear(parseInt(m[1], 10), parseInt(m[2], 10) - 1,
309             parseInt(m[3], 10));
310         d.setUTCHours(parseInt(m[4], 10), parseInt(m[5], 10));
311         if (m[6] && m[6].length > 0)
312                 d.setUTCSeconds(parseInt(m[6], 10));
313         return (d);
314 }
315
316 function zeroPad(n) {
317         var s = '' + n;
318         while (s.length < 2)
319                 s = '0' + s;
320         return (s);
321 }
322
323 function dateToUTCTime(d) {
324         var s = '';
325         s += zeroPad(d.getUTCFullYear() % 100);
326         s += zeroPad(d.getUTCMonth() + 1);
327         s += zeroPad(d.getUTCDate());
328         s += zeroPad(d.getUTCHours());
329         s += zeroPad(d.getUTCMinutes());
330         s += zeroPad(d.getUTCSeconds());
331         s += 'Z';
332         return (s);
333 }
334
335 function sign(cert, key) {
336         if (cert.signatures.x509 === undefined)
337                 cert.signatures.x509 = {};
338         var sig = cert.signatures.x509;
339
340         sig.algo = key.type + '-' + key.defaultHashAlgorithm();
341         if (SIGN_ALGS[sig.algo] === undefined)
342                 return (false);
343
344         var der = new asn1.BerWriter();
345         writeTBSCert(cert, der);
346         var blob = der.buffer;
347         sig.cache = blob;
348
349         var signer = key.createSign();
350         signer.write(blob);
351         cert.signatures.x509.signature = signer.sign();
352
353         return (true);
354 }
355
356 function write(cert, options) {
357         var sig = cert.signatures.x509;
358         assert.object(sig, 'x509 signature');
359
360         var der = new asn1.BerWriter();
361         der.startSequence();
362         if (sig.cache) {
363                 der._ensure(sig.cache.length);
364                 sig.cache.copy(der._buf, der._offset);
365                 der._offset += sig.cache.length;
366         } else {
367                 writeTBSCert(cert, der);
368         }
369
370         der.startSequence();
371         der.writeOID(SIGN_ALGS[sig.algo]);
372         if (sig.algo.match(/^rsa-/))
373                 der.writeNull();
374         der.endSequence();
375
376         var sigData = sig.signature.toBuffer('asn1');
377         var data = new Buffer(sigData.length + 1);
378         data[0] = 0;
379         sigData.copy(data, 1);
380         der.writeBuffer(data, asn1.Ber.BitString);
381         der.endSequence();
382
383         return (der.buffer);
384 }
385
386 function writeTBSCert(cert, der) {
387         var sig = cert.signatures.x509;
388         assert.object(sig, 'x509 signature');
389
390         der.startSequence();
391
392         der.startSequence(Local(0));
393         der.writeInt(2);
394         der.endSequence();
395
396         der.writeBuffer(utils.mpNormalize(cert.serial), asn1.Ber.Integer);
397
398         der.startSequence();
399         der.writeOID(SIGN_ALGS[sig.algo]);
400         der.endSequence();
401
402         cert.issuer.toAsn1(der);
403
404         der.startSequence();
405         der.writeString(dateToUTCTime(cert.validFrom), asn1.Ber.UTCTime);
406         der.writeString(dateToUTCTime(cert.validUntil), asn1.Ber.UTCTime);
407         der.endSequence();
408
409         var subject = cert.subjects[0];
410         var altNames = cert.subjects.slice(1);
411         subject.toAsn1(der);
412
413         pkcs8.writePkcs8(der, cert.subjectKey);
414
415         if (sig.extras && sig.extras.issuerUniqueID) {
416                 der.writeBuffer(sig.extras.issuerUniqueID, Local(1));
417         }
418
419         if (sig.extras && sig.extras.subjectUniqueID) {
420                 der.writeBuffer(sig.extras.subjectUniqueID, Local(2));
421         }
422
423         if (altNames.length > 0 || subject.type === 'host' ||
424             (sig.extras && sig.extras.exts)) {
425                 der.startSequence(Local(3));
426                 der.startSequence();
427
428                 var exts = [
429                         { oid: EXTS.altName }
430                 ];
431                 if (sig.extras && sig.extras.exts)
432                         exts = sig.extras.exts;
433
434                 for (var i = 0; i < exts.length; ++i) {
435                         der.startSequence();
436                         der.writeOID(exts[i].oid);
437
438                         if (exts[i].critical !== undefined)
439                                 der.writeBoolean(exts[i].critical);
440
441                         if (exts[i].oid === EXTS.altName) {
442                                 der.startSequence(asn1.Ber.OctetString);
443                                 der.startSequence();
444                                 if (subject.type === 'host') {
445                                         der.writeString(subject.hostname,
446                                             Context(2));
447                                 }
448                                 for (var j = 0; j < altNames.length; ++j) {
449                                         if (altNames[j].type === 'host') {
450                                                 der.writeString(
451                                                     altNames[j].hostname,
452                                                     ALTNAME.DNSName);
453                                         } else if (altNames[j].type ===
454                                             'email') {
455                                                 der.writeString(
456                                                     altNames[j].email,
457                                                     ALTNAME.RFC822Name);
458                                         } else {
459                                                 /*
460                                                  * Encode anything else as a
461                                                  * DN style name for now.
462                                                  */
463                                                 der.startSequence(
464                                                     ALTNAME.DirectoryName);
465                                                 altNames[j].toAsn1(der);
466                                                 der.endSequence();
467                                         }
468                                 }
469                                 der.endSequence();
470                                 der.endSequence();
471                         } else {
472                                 der.writeBuffer(exts[i].data,
473                                     asn1.Ber.OctetString);
474                         }
475
476                         der.endSequence();
477                 }
478
479                 der.endSequence();
480                 der.endSequence();
481         }
482
483         der.endSequence();
484 }