Permalink
Browse files

Constant time string comparison for hmac, closes #2

  • Loading branch information...
1 parent f718290 commit c6d1a123cba27c6dc94229d89fa607084999e715 @hueniverse committed Dec 21, 2012
Showing with 65 additions and 2 deletions.
  1. +21 −2 lib/index.js
  2. +44 −0 test/index.js
View
@@ -132,7 +132,7 @@ exports.authenticate = function (req, credentialsFunc, arg1, arg2) {
// Calculate MAC
var mac = exports.calculateMAC(credentials.key, credentials.algorithm, attributes.ts, attributes.nonce, req.method, req.url, host, port, attributes.ext);
- if (mac !== attributes.mac) {
+ if (!exports.fixedTimeComparison(mac, attributes.mac)) {
return callback(Err.unauthorized('Bad mac'), credentials, attributes.ext);
}
@@ -217,7 +217,7 @@ exports.parseHeader = function (header) {
if (verify !== '') {
return Err.badRequest('Unknown attributes');
}
-
+
return attributes;
};
@@ -271,3 +271,22 @@ exports.randomString = function (size) {
return result.join('');
};
+
+// Compare two strings using fixed time algorithm (to prevent time-based analysis of MAC digest match)
+
+exports.fixedTimeComparison = function (a, b) {
+
+ var mismatch = (a.length === b.length ? 0 : 1);
+ if (mismatch) {
+ b = a;
+ }
+
+ for (var i = 0, il = a.length; i < il; ++i) {
+ var ac = a.charCodeAt(i);
+ var bc = b.charCodeAt(i);
+ mismatch += (ac === bc ? 0 : 1);
+ }
+
+ return (mismatch === 0);
+};
+
View
@@ -531,5 +531,49 @@ describe('Hawk', function () {
done();
});
});
+
+ describe('#fixedTimeComparison', function () {
+
+ var a = Hawk.randomString(50000);
+ var b = Hawk.randomString(150000);
+
+ it('should take the same amount of time comparing different string sizes', function (done) {
+
+ var now = Date.now();
+ Hawk.fixedTimeComparison(b, a);
+ var t1 = Date.now() - now;
+
+ now = Date.now();
+ Hawk.fixedTimeComparison(b, b);
+ var t2 = Date.now() - now;
+
+ expect(t2 - t1).to.be.within(-1, 1);
+ done();
+ });
+
+ it('should return true for equal strings', function (done) {
+
+ expect(Hawk.fixedTimeComparison(a, a)).to.equal(true);
+ done();
+ });
+
+ it('should return false for different strings (size, a < b)', function (done) {
+
+ expect(Hawk.fixedTimeComparison(a, a + 'x')).to.equal(false);
+ done();
+ });
+
+ it('should return false for different strings (size, a > b)', function (done) {
+
+ expect(Hawk.fixedTimeComparison(a + 'x', a)).to.equal(false);
+ done();
+ });
+
+ it('should return false for different strings (size, a = b)', function (done) {
+
+ expect(Hawk.fixedTimeComparison(a + 'x', a + 'y')).to.equal(false);
+ done();
+ });
+ });
});

0 comments on commit c6d1a12

Please sign in to comment.