{"size": 2051, "ext": "js", "max_stars_repo_path": "node_modules/signer/index.js", "max_stars_repo_name": "pubsubio/pubsub-hub", "max_stars_repo_stars_event_min_datetime": "2015-01-07T00:25:40.000Z", "max_stars_repo_stars_event_max_datetime": "2019-04-16T09:04:47.000Z", "max_issues_repo_path": "node_modules/signer/index.js", "max_issues_repo_name": "pubsubio/pubsub-hub", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "node_modules/signer/index.js", "max_forks_repo_name": "pubsubio/pubsub-hub", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 3, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 20.7171717172, "max_line_length": 81, "alphanum_fraction": 0.5987323257}
var crypto = require('crypto');
var common = require('common');
var fs = require('fs');

var esc = function() {
	var map = {'=':'-','+':'*','/':'_'};
	
	return function(str) {
		return str.replace(/[=+\/]/g, function(a) {
			return map[a];
		});		
	};
}();
var unesc = function() {
	var map = {'-':'=','*':'+','_':'/'};
	
	return function(str) {
		return str.replace(/[-*_]/g, function(a) {
			return map[a];
		});		
	};
}();
var hmac = function(str, secret) {
	var hash = crypto.createHmac('sha1', secret);
	
	hash.update(str);
	
	return hash.digest('base64');
};

var sign = function(secret, str, options) {
	options = options || {};
	
	var now = options.ttl ? ((Date.now()/1000)|0)+options.ttl : 0;
		
	return esc(new Buffer(''+now).toString('base64')+'!'+hmac(now+','+str, secret));
};
var verify = function(secret, str, sig) {
	sig = unesc(sig).split('!');
	
	if (sig.length !== 2) {
		return false;
	}

	var exp = parseInt(new Buffer(sig[0], 'base64').toString('ascii'),10);
	
	sig = sig[1];

	if (hmac(exp+','+str, secret) !== sig) {
		return false;
	}
		
	return !exp || 1000*exp >= Date.now();
};

var Signer = function(secret) {
	this.secret = secret;
};

Signer.prototype.sign = function(str, options) {
	return sign(this.secret, str, options);
};
Signer.prototype.verify = function(str, sig) {
	return verify(this.secret, str, sig);
};

try {
	exports.secret = require('fs').readFileSync(__dirname+'/shared.key');
} catch (err) {}

exports.generateKey = function(callback) {
	var result = new Buffer(20);

	common.step([
		function(next) {
			fs.open('/dev/random', 'r', 0666, next);				
		},
		function(fd, next) {
			this.fd = fd;
			fs.read(fd, result, 0, 20, null, next);
		},
		function(read, next) {
			fs.close(this.fd, next);
		},
		function() {
			callback(null, result);
		}
	], callback)	
}
exports.sign = function(str, options) {
	return sign(exports.secret, str, options);
};
exports.verify = function(str, sig) {
	return verify(exports.secret, str, sig);
};
exports.create = function(secret) {
	return new Signer(secret);
};
