Georg Reisinger b171f1646c GoogleOauth2.0 First implementation
First try for GoogleOauth2.0
2018-10-26 14:02:15 +02:00

72 lines
1.6 KiB
JavaScript

/*!
* keygrip
* Copyright(c) 2011-2014 Jed Schmidt
* MIT Licensed
*/
'use strict'
var crypto = require("crypto")
function Keygrip(keys, algorithm, encoding) {
if (!algorithm) algorithm = "sha1";
if (!encoding) encoding = "base64";
if (!(this instanceof Keygrip)) return new Keygrip(keys, algorithm, encoding)
if (!keys || !(0 in keys)) {
throw new Error("Keys must be provided.")
}
function sign(data, key) {
return crypto
.createHmac(algorithm, key)
.update(data).digest(encoding)
.replace(/\/|\+|=/g, function(x) {
return ({ "/": "_", "+": "-", "=": "" })[x]
})
}
this.sign = function(data){ return sign(data, keys[0]) }
this.verify = function(data, digest) {
return this.index(data, digest) > -1
}
this.index = function(data, digest) {
for (var i = 0, l = keys.length; i < l; i++) {
if (constantTimeCompare(digest, sign(data, keys[i]))) return i
}
return -1
}
}
Keygrip.sign = Keygrip.verify = Keygrip.index = function() {
throw new Error("Usage: require('keygrip')(<array-of-keys>)")
}
//http://codahale.com/a-lesson-in-timing-attacks/
var constantTimeCompare = function(val1, val2){
if(val1 == null && val2 != null){
return false;
} else if(val2 == null && val1 != null){
return false;
} else if(val1 == null && val2 == null){
return true;
}
if(val1.length !== val2.length){
return false;
}
var result = 0;
for(var i = 0; i < val1.length; i++){
result |= val1.charCodeAt(i) ^ val2.charCodeAt(i); //Don't short circuit
}
return result === 0;
};
module.exports = Keygrip