bridge-node-server/node_server/utils/hashing.spec.js
Martin Donnelly 57bd6c8e6a init
2018-06-24 21:15:03 +01:00

126 lines
4.4 KiB
JavaScript

var hashUtils = require('./hashing.js');
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
var expect = chai.expect;
chai.use(chaiAsPromised);
//
// Sample data
//
const samplePassword = '5678';
const incorrectPassword = '5679';
//
// Current max password version
//
const latestVersion = 2;
//
// Sample V1 hash: actually just a direct compare
//
const sampleHashV1 = '5678';
//
// Sample V2 values. Calculated indepedently using the Standford Javascript
// Crypto Library: http://bitwiseshiftleft.github.io/sjcl/
//
const sampleHashV2 = '2::920290ac3bc5f38d78ca46a2e714da6f0e45a080d2a0259e09bc04cfa3d9b081';
const sampleSaltV2 = '1ba8b6f708f075241f3d7cd9d63e0664b62e98f01ca83aafa453896fa49e8f1a';
describe('Hashing utilities', function() {
describe('generateHash', function() {
it('should give hash+salt', function() {
var result = hashUtils.generateHash(2, samplePassword);
return expect(result).to.eventually.have.property('hash');
});
it('should match on verify', function() {
var hash = hashUtils.generateHash(2, samplePassword);
var result = hash.then(function(newHash) {
return hashUtils.verifyHash(samplePassword, newHash.hash, newHash.salt, latestVersion);
});
return expect(result).to.eventually.be.fulfilled;
});
});
describe('valid v1 hash with matching password', function() {
var result = null;
beforeEach('call verifyHash', function() {
result = hashUtils.verifyHash(samplePassword, sampleHashV1, '', latestVersion);
});
it('should match a v1 hash', function() {
return expect(result).to.eventually.be.fulfilled;
});
it('should generate a v2 hash', function() {
return expect(result).to.eventually.have.property('hash');
});
it('should generate a new salt', function() {
return expect(result).to.eventually.have.property('salt');
});
it('should generate a 64 character salt (32 bytes = 64 hex chars)', function() {
return result.then(function(newHash) {
expect(newHash.salt).to.have.length(64);
});
});
it('should generate a 67 character hash ("2::" + 32 bytes/64 hex chars)', function() {
return result.then(function(newHash) {
expect(newHash.hash).to.have.length(67);
});
});
it('should generate a hash in the right format', function() {
return result.then(function(newHash) {
expect(newHash.hash).to.match(/^2::[0-9a-z]{64}$/);
});
});
});
describe('valid v2 hash with matching password', function() {
var result = null;
beforeEach('call verifyHash', function() {
result = hashUtils.verifyHash(samplePassword, sampleHashV2, sampleSaltV2, latestVersion);
});
it('should match a v2 hash', function() {
return expect(result).to.eventually.be.fulfilled;
});
it('should not generate a new hash/salt (already latest version)', function() {
return expect(result).to.eventually.equal(null);
});
});
describe('wrong password', function() {
it('should not match a v1 hash', function() {
var result = hashUtils.verifyHash(incorrectPassword, sampleHashV1, '', latestVersion);
return expect(result).to.eventually.be.rejectedWith(hashUtils.ERRORS.NO_MATCH);
});
it('should not match a v2 hash', function() {
var result = hashUtils.verifyHash(incorrectPassword, sampleHashV2, '', latestVersion);
return expect(result).to.eventually.be.rejectedWith(hashUtils.ERRORS.NO_MATCH);
});
});
describe('unknown latest version', function() {
it('v1 hash should fail to generate a new hash/salt', function() {
var result = hashUtils.verifyHash(samplePassword, sampleHashV1, '', latestVersion + 1);
return expect(result).to.eventually.be.rejectedWith(hashUtils.ERRORS.UNKNOWN_ALGO);
});
it('v2 hash should fail to generate a new hash/salt', function() {
var result = hashUtils.verifyHash(samplePassword, sampleHashV2, sampleSaltV2, latestVersion + 1);
return expect(result).to.eventually.be.rejectedWith(hashUtils.ERRORS.UNKNOWN_ALGO);
});
});
});