@yawetse/pkgcloud
Version:
An infrastructure-as-a-service agnostic cloud library for node.js
127 lines (107 loc) • 2.96 kB
JavaScript
/*
* http-signature.js: Implmentation of `http-signature` authentication.
*
* Copyright (C) 2011 Joyent, Inc. All rights reserved.
* MIT License
*
* Modified under MIT
*
*/
var crypto = require('crypto');
//
// ## Globals
//
var Algorithms = {
'rsa-sha1': true,
'rsa-sha256': true,
'rsa-sha512': true,
'dsa-sha1': true,
'hmac-sha1': true,
'hmac-sha256': true,
'hmac-sha512': true
};
//
// ## Specific Errors
//
function MissingHeaderError(message) {
this.name = 'MissingHeaderError';
this.message = message;
this.stack = (new Error()).stack;
}
MissingHeaderError.prototype = new Error();
function InvalidAlgorithmError(message) {
this.name = 'InvalidAlgorithmError';
this.message = message;
this.stack = (new Error()).stack;
}
InvalidAlgorithmError.prototype = new Error();
//
// ## Internal Functions
//
function _pad(val) {
return parseInt(val, 10) < 10
? val = '0' + val
: val;
}
function _rfc1123() {
var date = new Date(),
months,
days;
days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
months = [
'Jan', 'Feb', 'Mar',
'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'
];
return days[date.getUTCDay()] + ', ' +
_pad(date.getUTCDate()) + ' ' +
months[date.getUTCMonth()] + ' ' +
date.getUTCFullYear() + ' ' +
_pad(date.getUTCHours()) + ':' +
_pad(date.getUTCMinutes()) + ':' +
_pad(date.getUTCSeconds()) + ' GMT';
}
//
// ## Exported API methods
//
module.exports = {
sign: function (req, options) {
if (!options || !(options instanceof Object)) {
throw new TypeError('options must be an Object');
}
if (!options.keyId || typeof options.keyId !== 'string') {
throw new TypeError('options.keyId must be a String');
}
if (options.algorithm && typeof options.algorithm !== 'string') {
throw new TypeError('options.algorithm must be a String');
}
if (!options.algorithm) {
options.algorithm = 'rsa-sha256';
}
options.algorithm = options.algorithm.toLowerCase();
if (!Algorithms[options.algorithm]) {
throw new InvalidAlgorithmError(options.algorithm + ' is not supported');
}
var stringToSign = _rfc1123(),
alg = options.algorithm.match(/(hmac|rsa)-(\w+)/),
signature,
signer,
hmac;
if (alg[1] === 'hmac') {
hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
hmac.update(stringToSign);
signature = hmac.digest('base64');
} else {
signer = crypto.createSign(options.algorithm.toUpperCase());
signer.update(stringToSign);
signature = signer.sign(options.key, 'base64');
}
req.headers = req.headers || {};
req.headers.date = stringToSign;
req.headers.Authorization =
'Signature keyId="' + options.keyId + '",algorithm="' +
options.algorithm + '",headers="date" ' + signature;
return req;
}
};