"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/http-signature/lib/signer.js" (7 Feb 2017, 5203 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2012 Joyent, Inc.  All rights reserved.
    2 
    3 var assert = require('assert-plus');
    4 var crypto = require('crypto');
    5 var http = require('http');
    6 
    7 var sprintf = require('util').format;
    8 
    9 
   10 
   11 ///--- Globals
   12 
   13 var Algorithms = {
   14   'rsa-sha1': true,
   15   'rsa-sha256': true,
   16   'rsa-sha512': true,
   17   'dsa-sha1': true,
   18   'hmac-sha1': true,
   19   'hmac-sha256': true,
   20   'hmac-sha512': true
   21 };
   22 
   23 var Authorization =
   24   'Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"';
   25 
   26 
   27 
   28 ///--- Specific Errors
   29 
   30 function MissingHeaderError(message) {
   31     this.name = 'MissingHeaderError';
   32     this.message = message;
   33     this.stack = (new Error()).stack;
   34 }
   35 MissingHeaderError.prototype = new Error();
   36 
   37 
   38 function InvalidAlgorithmError(message) {
   39     this.name = 'InvalidAlgorithmError';
   40     this.message = message;
   41     this.stack = (new Error()).stack;
   42 }
   43 InvalidAlgorithmError.prototype = new Error();
   44 
   45 
   46 
   47 ///--- Internal Functions
   48 
   49 function _pad(val) {
   50   if (parseInt(val, 10) < 10) {
   51     val = '0' + val;
   52   }
   53   return val;
   54 }
   55 
   56 
   57 function _rfc1123() {
   58   var date = new Date();
   59 
   60   var months = ['Jan',
   61                 'Feb',
   62                 'Mar',
   63                 'Apr',
   64                 'May',
   65                 'Jun',
   66                 'Jul',
   67                 'Aug',
   68                 'Sep',
   69                 'Oct',
   70                 'Nov',
   71                 'Dec'];
   72   var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
   73   return days[date.getUTCDay()] + ', ' +
   74     _pad(date.getUTCDate()) + ' ' +
   75     months[date.getUTCMonth()] + ' ' +
   76     date.getUTCFullYear() + ' ' +
   77     _pad(date.getUTCHours()) + ':' +
   78     _pad(date.getUTCMinutes()) + ':' +
   79     _pad(date.getUTCSeconds()) +
   80     ' GMT';
   81 }
   82 
   83 
   84 
   85 ///--- Exported API
   86 
   87 module.exports = {
   88 
   89   /**
   90    * Adds an 'Authorization' header to an http.ClientRequest object.
   91    *
   92    * Note that this API will add a Date header if it's not already set. Any
   93    * other headers in the options.headers array MUST be present, or this
   94    * will throw.
   95    *
   96    * You shouldn't need to check the return type; it's just there if you want
   97    * to be pedantic.
   98    *
   99    * @param {Object} request an instance of http.ClientRequest.
  100    * @param {Object} options signing parameters object:
  101    *                   - {String} keyId required.
  102    *                   - {String} key required (either a PEM or HMAC key).
  103    *                   - {Array} headers optional; defaults to ['date'].
  104    *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
  105    *                   - {String} httpVersion optional; defaults to '1.1'.
  106    * @return {Boolean} true if Authorization (and optionally Date) were added.
  107    * @throws {TypeError} on bad parameter types (input).
  108    * @throws {InvalidAlgorithmError} if algorithm was bad.
  109    * @throws {MissingHeaderError} if a header to be signed was specified but
  110    *                              was not present.
  111    */
  112   signRequest: function signRequest(request, options) {
  113     assert.object(request, 'request');
  114     assert.object(options, 'options');
  115     assert.optionalString(options.algorithm, 'options.algorithm');
  116     assert.string(options.keyId, 'options.keyId');
  117     assert.optionalArrayOfString(options.headers, 'options.headers');
  118     assert.optionalString(options.httpVersion, 'options.httpVersion');
  119 
  120     if (!request.getHeader('Date'))
  121       request.setHeader('Date', _rfc1123());
  122     if (!options.headers)
  123       options.headers = ['date'];
  124     if (!options.algorithm)
  125       options.algorithm = 'rsa-sha256';
  126     if (!options.httpVersion)
  127       options.httpVersion = '1.1';
  128 
  129     options.algorithm = options.algorithm.toLowerCase();
  130 
  131     if (!Algorithms[options.algorithm])
  132       throw new InvalidAlgorithmError(options.algorithm + ' is not supported');
  133 
  134     var i;
  135     var stringToSign = '';
  136     for (i = 0; i < options.headers.length; i++) {
  137       if (typeof (options.headers[i]) !== 'string')
  138         throw new TypeError('options.headers must be an array of Strings');
  139 
  140       var h = options.headers[i].toLowerCase();
  141 
  142       if (h !== 'request-line') {
  143         var value = request.getHeader(h);
  144         if (!value) {
  145           throw new MissingHeaderError(h + ' was not in the request');
  146         }
  147         stringToSign += h + ': ' + value;
  148       } else {
  149         stringToSign +=
  150           request.method + ' ' + request.path + ' HTTP/' + options.httpVersion;
  151       }
  152 
  153       if ((i + 1) < options.headers.length)
  154         stringToSign += '\n';
  155     }
  156 
  157     var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
  158     var signature;
  159     if (alg[1] === 'hmac') {
  160       var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
  161       hmac.update(stringToSign);
  162       signature = hmac.digest('base64');
  163     } else {
  164       var signer = crypto.createSign(options.algorithm.toUpperCase());
  165       signer.update(stringToSign);
  166       signature = signer.sign(options.key, 'base64');
  167     }
  168 
  169     request.setHeader('Authorization', sprintf(Authorization,
  170                                                options.keyId,
  171                                                options.algorithm,
  172                                                options.headers.join(' '),
  173                                                signature));
  174 
  175     return true;
  176   }
  177 
  178 };