diff --git a/index.js b/index.js index f742f94..82d1537 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ var pbkdf2 = require('pbkdf2'); var createHmac = require('create-hmac'); var Promise = require("bluebird"); +var v2 = require('./src/v2'); module.exports = { encryptLogin: _encryptLogin, @@ -12,7 +13,8 @@ module.exports = { _string2charCodes: _string2charCodes, _getCharType: _getCharType, _getPasswordChar: _getPasswordChar, - _createHmac: _createHmac + _createHmac: _createHmac, + _calcEntropy: v2.calcEntropy }; function _encryptLogin(login, masterPassword, options) { diff --git a/package.json b/package.json index 46763ea..1cc8b70 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "scripts": { "build": "rimraf lib && mkdir lib && browserify --standalone LessPass index.js > lib/lesspass.js && gulp", "prepublish": "npm test && npm run build && npm run test:node && npm run test:browser", - "test": "mocha --require ./tests/helper.js tests", + "test": "mocha --require ./tests/helper.js tests/*", "test:node": "npm run build && cd tests && node node.js && cd ..", "test:webcrypto": "karma start tests/karma.webcrypto.config.js", "test:browser": "npm run build && karma start tests/karma.config.js" diff --git a/src/v2.js b/src/v2.js new file mode 100644 index 0000000..13c59cc --- /dev/null +++ b/src/v2.js @@ -0,0 +1,18 @@ +var Promise = require("bluebird"); +var pbkdf2 = require('pbkdf2'); + +exports.calcEntropy = function (site, login, masterPassword, passwordProfile) { + return new Promise(function (resolve, reject) { + var salt = site + login + passwordProfile.counter.toString(16); + var iterations = passwordProfile.iterations || 100000; + var keylen = passwordProfile.keylen || 32; + var digest = passwordProfile.digest || 'sha256'; + pbkdf2.pbkdf2(masterPassword, salt, iterations, keylen, digest, function (error, key) { + if (error) { + reject('error in pbkdf2'); + } else { + resolve(key.toString('hex')); + } + }); + }) +}; \ No newline at end of file diff --git a/tests/v2/entropy.tests.js b/tests/v2/entropy.tests.js new file mode 100644 index 0000000..80897f0 --- /dev/null +++ b/tests/v2/entropy.tests.js @@ -0,0 +1,53 @@ +var assert = chai.assert; + +describe('LessPass', function () { + describe('entropy', function () { + it('calc entropy pbkdf2 with default params (100000 iterations, 32 bytes length, sha256 digest)', function () { + this.timeout(10000); + var site = 'example.org'; + var login = 'contact@example.org'; + var masterPassword = 'password'; + var passwordProfile = { + counter: 1 + }; + return LessPass._calcEntropy(site, login, masterPassword, passwordProfile).then(function (entropy) { + assert.equal('dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e', entropy); + }) + }); + + it('calc entropy with different options (8192 iterations, 16 bytes length, sha512 digest)', function () { + var site = 'example.org'; + var login = 'contact@example.org'; + var masterPassword = 'password'; + var passwordProfile = { + iterations: 8192, + keylen: 16, + digest: 'sha512', + counter: 1 + }; + return LessPass._calcEntropy(site, login, masterPassword, passwordProfile).then(function (entropy) { + assert.equal('fff211c16a4e776b3574c6a5c91fd252', entropy); + }) + }); + + it('calc entropy different if counter different', function () { + var site = 'example.org'; + var login = 'contact@example.org'; + var masterPassword = 'password'; + var passwordProfile1 = { + iterations: 1, + counter: 1 + }; + var passwordProfile2 = { + iterations: 1, + counter: 2 + }; + var p1 = LessPass._calcEntropy(site, login, masterPassword, passwordProfile1); + var p2 = LessPass._calcEntropy(site, login, masterPassword, passwordProfile2); + return Promise.all([p1, p2]).then(function (entropies) { + assert.notEqual(entropies[0], entropies[1]) + }); + }); + + }); +}); \ No newline at end of file