Browse Source

add .editorconfig and auto format

pull/342/head
Guillaume Vincent 7 years ago
parent
commit
d66a896524
18 changed files with 1266 additions and 1288 deletions
  1. +17
    -0
      .editorconfig
  2. +22
    -22
      example/lesspass.html
  3. +48
    -48
      src/lesspass.js
  4. +36
    -36
      src/pbkdf2.js
  5. +70
    -70
      src/v1.js
  6. +52
    -52
      src/v2.js
  7. +28
    -28
      tests/karma.config.js
  8. +14
    -14
      tests/node.js
  9. +7
    -7
      tests/pbkdf2.tests.js
  10. +535
    -574
      tests/v1/api.tests.js
  11. +79
    -79
      tests/v1/deriveEncryptedLogin.tests.js
  12. +58
    -58
      tests/v1/getPasswordTemplate.tests.js
  13. +31
    -31
      tests/v1/prettyPrint.js
  14. +74
    -74
      tests/v2/api.tests.js
  15. +54
    -54
      tests/v2/entropy.tests.js
  16. +67
    -67
      tests/v2/renderPassword.tests.js
  17. +55
    -55
      tests/v2/setOfCharacters.tests.js
  18. +19
    -19
      webpack.config.js

+ 17
- 0
.editorconfig View File

@@ -0,0 +1,17 @@
# editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.py]
indent_size = 4

+ 22
- 22
example/lesspass.html View File

@@ -1,31 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="../dist/lesspass.js"></script>
<meta charset="UTF-8">
<script src="../dist/lesspass.js"></script>
</head>
<body>
<script>
const site = 'example.org';
const login = 'contact@example.org';
const masterPassword = 'password';
const passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
length: 16,
counter: 1,
version: 2
};
LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function (generatedPassword) {
console.log(generatedPassword); //WHLpUL)e00[iHR+w
document.body.innerHTML = document.body.innerHTML + "<br>generated password : <b>" + generatedPassword + "</b> === WHLpUL)e00[iHR+w"
});
const site = 'example.org';
const login = 'contact@example.org';
const masterPassword = 'password';
const passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
length: 16,
counter: 1,
version: 2
};
LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function(generatedPassword) {
console.log(generatedPassword); //WHLpUL)e00[iHR+w
document.body.innerHTML = document.body.innerHTML + "<br>generated password : <b>" + generatedPassword + "</b> === WHLpUL)e00[iHR+w"
});

LessPass.createFingerprint('password').then(fingerprint => {
document.body.innerHTML = document.body.innerHTML + "fingerprint : " + fingerprint
});
LessPass.createFingerprint('password').then(fingerprint => {
document.body.innerHTML = document.body.innerHTML + "fingerprint : " + fingerprint
});
</script>
</body>
</html>
</html>

+ 48
- 48
src/lesspass.js View File

@@ -4,59 +4,59 @@ var pbkdf2 = require('./pbkdf2');
var objectAssign = require('object-assign');

module.exports = {
encryptLogin: v1.encryptLogin,
renderPassword: v1.renderPassword,
createFingerprint: v1.createFingerprint,
_deriveEncryptedLogin: v1._deriveEncryptedLogin,
_getPasswordTemplate: v1._getPasswordTemplate,
_prettyPrint: v1._prettyPrint,
_string2charCodes: v1._string2charCodes,
_getCharType: v1._getCharType,
_getPasswordChar: v1._getPasswordChar,
_createHmac: v1._createHmac,
encryptLogin: v1.encryptLogin,
renderPassword: v1.renderPassword,
createFingerprint: v1.createFingerprint,
_deriveEncryptedLogin: v1._deriveEncryptedLogin,
_getPasswordTemplate: v1._getPasswordTemplate,
_prettyPrint: v1._prettyPrint,
_string2charCodes: v1._string2charCodes,
_getCharType: v1._getCharType,
_getPasswordChar: v1._getPasswordChar,
_createHmac: v1._createHmac,

generatePassword: generatePassword,
_calcEntropy: v2._calcEntropy,
_consumeEntropy: v2._consumeEntropy,
_getSetOfCharacters: v2._getSetOfCharacters,
_getConfiguredRules: v2._getConfiguredRules,
_insertStringPseudoRandomly: v2._insertStringPseudoRandomly,
_getOneCharPerRule: v2._getOneCharPerRule,
_renderPassword: v2._renderPassword,
generatePassword: generatePassword,
_calcEntropy: v2._calcEntropy,
_consumeEntropy: v2._consumeEntropy,
_getSetOfCharacters: v2._getSetOfCharacters,
_getConfiguredRules: v2._getConfiguredRules,
_insertStringPseudoRandomly: v2._insertStringPseudoRandomly,
_getOneCharPerRule: v2._getOneCharPerRule,
_renderPassword: v2._renderPassword,

pbkdf2: pbkdf2
pbkdf2: pbkdf2
};

var defaultPasswordProfile = {
version: 2,
lowercase: true,
numbers: true,
uppercase: true,
symbols: true,
keylen: 32,
digest: 'sha256',
length: 16,
index: 1,
iterations: 100000
version: 2,
lowercase: true,
numbers: true,
uppercase: true,
symbols: true,
keylen: 32,
digest: 'sha256',
length: 16,
index: 1,
iterations: 100000
};

function generatePassword(site, login, masterPassword, passwordProfile) {
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
if (_passwordProfile.version === 1) {
var options = {
counter: _passwordProfile.counter,
length: _passwordProfile.length,
lowercase: _passwordProfile.lowercase,
uppercase: _passwordProfile.uppercase,
numbers: _passwordProfile.numbers,
symbols: _passwordProfile.symbols
};
return v1.encryptLogin(login, masterPassword)
.then(function (encryptedLogin) {
return v1.renderPassword(encryptedLogin, site, options).then(function (generatedPassword) {
return generatedPassword
});
});
}
return v2.generatePassword(site, login, masterPassword, _passwordProfile);
}
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
if (_passwordProfile.version === 1) {
var options = {
counter: _passwordProfile.counter,
length: _passwordProfile.length,
lowercase: _passwordProfile.lowercase,
uppercase: _passwordProfile.uppercase,
numbers: _passwordProfile.numbers,
symbols: _passwordProfile.symbols
};
return v1.encryptLogin(login, masterPassword)
.then(function(encryptedLogin) {
return v1.renderPassword(encryptedLogin, site, options).then(function(generatedPassword) {
return generatedPassword
});
});
}
return v2.generatePassword(site, login, masterPassword, _passwordProfile);
}

+ 36
- 36
src/pbkdf2.js View File

@@ -3,49 +3,49 @@ var Promise = require('pinkie-promise');


function shouldUseNative() {
return !!(typeof window !== 'undefined' && window.crypto && window.crypto.subtle);
return !!(typeof window !== 'undefined' && window.crypto && window.crypto.subtle);
}

function pbkdf2Native(password, salt, iterations, keylen, digest) {
var algorithms = {
'sha1': 'SHA-1',
'sha-1': 'SHA-1',
'sha256': 'SHA-256',
'sha-256': 'SHA-256',
'sha512': 'SHA-512',
'sha-512': 'SHA-512',
};
return window.crypto.subtle.importKey('raw', new Buffer(password), 'PBKDF2', false, ['deriveKey'])
.then(function (key) {
var algo = {
name: 'PBKDF2',
salt: new Buffer(salt),
iterations: iterations,
hash: algorithms[digest.toLowerCase()],
};
return window.crypto.subtle.deriveKey(algo, key, {
name: 'AES-CTR',
length: keylen * 8
}, true, ['encrypt', 'decrypt']);
})
.then(function (derivedKey) {
return window.crypto.subtle.exportKey('raw', derivedKey).then(function (keyArray) {
return new Buffer(keyArray).toString('hex');
});
});
var algorithms = {
'sha1': 'SHA-1',
'sha-1': 'SHA-1',
'sha256': 'SHA-256',
'sha-256': 'SHA-256',
'sha512': 'SHA-512',
'sha-512': 'SHA-512',
};
return window.crypto.subtle.importKey('raw', new Buffer(password), 'PBKDF2', false, ['deriveKey'])
.then(function(key) {
var algo = {
name: 'PBKDF2',
salt: new Buffer(salt),
iterations: iterations,
hash: algorithms[digest.toLowerCase()],
};
return window.crypto.subtle.deriveKey(algo, key, {
name: 'AES-CTR',
length: keylen * 8
}, true, ['encrypt', 'decrypt']);
})
.then(function(derivedKey) {
return window.crypto.subtle.exportKey('raw', derivedKey).then(function(keyArray) {
return new Buffer(keyArray).toString('hex');
});
});
}

function pbkdf2Browserified(password, salt, iterations, keylen, digest) {
return new Promise(function (resolve, reject) {
pbkdf2.pbkdf2(password, salt, iterations, keylen, digest, function (error, key) {
if (error) {
reject('error in pbkdf2');
} else {
resolve(key.toString('hex'));
}
});
return new Promise(function(resolve, reject) {
pbkdf2.pbkdf2(password, salt, iterations, keylen, digest, function(error, key) {
if (error) {
reject('error in pbkdf2');
} else {
resolve(key.toString('hex'));
}
});
});
}


module.exports = shouldUseNative() ? pbkdf2Native : pbkdf2Browserified;
module.exports = shouldUseNative() ? pbkdf2Native : pbkdf2Browserified;

+ 70
- 70
src/v1.js View File

@@ -4,106 +4,106 @@ var Promise = require('pinkie-promise');


module.exports = {
encryptLogin: encryptLogin,
renderPassword: renderPassword,
createFingerprint: createFingerprint,
_deriveEncryptedLogin: deriveEncryptedLogin,
_getPasswordTemplate: getPasswordTemplate,
_prettyPrint: prettyPrint,
_string2charCodes: string2charCodes,
_getCharType: getCharType,
_getPasswordChar: getPasswordChar,
_createHmac: createHmac,
encryptLogin: encryptLogin,
renderPassword: renderPassword,
createFingerprint: createFingerprint,
_deriveEncryptedLogin: deriveEncryptedLogin,
_getPasswordTemplate: getPasswordTemplate,
_prettyPrint: prettyPrint,
_string2charCodes: string2charCodes,
_getCharType: getCharType,
_getPasswordChar: getPasswordChar,
_createHmac: createHmac,
};


function encryptLogin(login, masterPassword, options) {
var _options = options !== undefined ? options : {};
var iterations = _options.iterations || 8192;
var keylen = _options.keylen || 32;
return pbkdf2(masterPassword, login, iterations, keylen, 'sha256');
var _options = options !== undefined ? options : {};
var iterations = _options.iterations || 8192;
var keylen = _options.keylen || 32;
return pbkdf2(masterPassword, login, iterations, keylen, 'sha256');
}

function renderPassword(encryptedLogin, site, passwordOptions) {
return deriveEncryptedLogin(encryptedLogin, site, passwordOptions).then(function (derivedEncryptedLogin) {
var template = passwordOptions.template || getPasswordTemplate(passwordOptions);
return prettyPrint(derivedEncryptedLogin, template);
});
return deriveEncryptedLogin(encryptedLogin, site, passwordOptions).then(function(derivedEncryptedLogin) {
var template = passwordOptions.template || getPasswordTemplate(passwordOptions);
return prettyPrint(derivedEncryptedLogin, template);
});
}

function createHmac(encryptedLogin, salt) {
return new Promise(function (resolve) {
resolve(createHMAC('sha256', new Buffer(encryptedLogin)).update(salt).digest('hex'));
});
return new Promise(function(resolve) {
resolve(createHMAC('sha256', new Buffer(encryptedLogin)).update(salt).digest('hex'));
});
}

function deriveEncryptedLogin(encryptedLogin, site, options) {
var _options = options !== undefined ? options : {};
var length = _options.length || 12;
var counter = _options.counter || 1;
var _options = options !== undefined ? options : {};
var length = _options.length || 12;
var counter = _options.counter || 1;

var salt = site + counter.toString();
return createHmac(encryptedLogin, salt).then(function (derivedHash) {
return derivedHash.substring(0, length);
});
var salt = site + counter.toString();
return createHmac(encryptedLogin, salt).then(function(derivedHash) {
return derivedHash.substring(0, length);
});
}

function getPasswordTemplate(passwordTypes) {
var templates = {
lowercase: 'vc',
uppercase: 'VC',
numbers: 'n',
symbols: 's',
};
var returnedTemplate = '';
Object.keys(templates).forEach(function (template) {
if (passwordTypes.hasOwnProperty(template) && passwordTypes[template]) {
returnedTemplate += templates[template]
}
});
return returnedTemplate;
var templates = {
lowercase: 'vc',
uppercase: 'VC',
numbers: 'n',
symbols: 's',
};
var returnedTemplate = '';
Object.keys(templates).forEach(function(template) {
if (passwordTypes.hasOwnProperty(template) && passwordTypes[template]) {
returnedTemplate += templates[template]
}
});
return returnedTemplate;
}

function prettyPrint(hash, template) {
var password = '';
var password = '';

string2charCodes(hash).forEach(function (charCode, index) {
var charType = getCharType(template, index);
password += getPasswordChar(charType, charCode);
});
return password;
string2charCodes(hash).forEach(function(charCode, index) {
var charType = getCharType(template, index);
password += getPasswordChar(charType, charCode);
});
return password;
}

function string2charCodes(text) {
var charCodes = [];
for (var i = 0; i < text.length; i++) {
charCodes.push(text.charCodeAt(i));
}
return charCodes;
var charCodes = [];
for (var i = 0; i < text.length; i++) {
charCodes.push(text.charCodeAt(i));
}
return charCodes;
}

function getCharType(template, index) {
return template[index % template.length];
return template[index % template.length];
}

function getPasswordChar(charType, index) {
var passwordsChars = {
V: 'AEIOUY',
C: 'BCDFGHJKLMNPQRSTVWXZ',
v: 'aeiouy',
c: 'bcdfghjklmnpqrstvwxz',
A: 'AEIOUYBCDFGHJKLMNPQRSTVWXZ',
a: 'AEIOUYaeiouyBCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz',
n: '0123456789',
s: '@&%?,=[]_:-+*$#!\'^~;()/.',
x: 'AEIOUYaeiouyBCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz0123456789@&%?,=[]_:-+*$#!\'^~;()/.'
};
var passwordChar = passwordsChars[charType];
return passwordChar[index % passwordChar.length];
var passwordsChars = {
V: 'AEIOUY',
C: 'BCDFGHJKLMNPQRSTVWXZ',
v: 'aeiouy',
c: 'bcdfghjklmnpqrstvwxz',
A: 'AEIOUYBCDFGHJKLMNPQRSTVWXZ',
a: 'AEIOUYaeiouyBCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz',
n: '0123456789',
s: '@&%?,=[]_:-+*$#!\'^~;()/.',
x: 'AEIOUYaeiouyBCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz0123456789@&%?,=[]_:-+*$#!\'^~;()/.'
};
var passwordChar = passwordsChars[charType];
return passwordChar[index % passwordChar.length];
}

function createFingerprint(str) {
return new Promise(function (resolve) {
resolve(createHMAC('sha256', new Buffer(str)).digest('hex'))
});
}
return new Promise(function(resolve) {
resolve(createHMAC('sha256', new Buffer(str)).digest('hex'))
});
}

+ 52
- 52
src/v2.js View File

@@ -2,83 +2,83 @@ var pbkdf2 = require('./pbkdf2');
var bigInt = require("big-integer");

module.exports = {
generatePassword: generatePassword,
_calcEntropy: calcEntropy,
_consumeEntropy: consumeEntropy,
_getSetOfCharacters: getSetOfCharacters,
_getConfiguredRules: getConfiguredRules,
_insertStringPseudoRandomly: insertStringPseudoRandomly,
_getOneCharPerRule: getOneCharPerRule,
_renderPassword: renderPassword
generatePassword: generatePassword,
_calcEntropy: calcEntropy,
_consumeEntropy: consumeEntropy,
_getSetOfCharacters: getSetOfCharacters,
_getConfiguredRules: getConfiguredRules,
_insertStringPseudoRandomly: insertStringPseudoRandomly,
_getOneCharPerRule: getOneCharPerRule,
_renderPassword: renderPassword
};

function generatePassword(site, login, masterPassword, passwordProfile) {
return calcEntropy(site, login, masterPassword, passwordProfile).then(function (entropy) {
return renderPassword(entropy, passwordProfile);
});
return calcEntropy(site, login, masterPassword, passwordProfile).then(function(entropy) {
return renderPassword(entropy, passwordProfile);
});
}

function calcEntropy(site, login, masterPassword, passwordProfile) {
var salt = site + login + passwordProfile.counter.toString(16);
return pbkdf2(masterPassword, salt, passwordProfile.iterations, passwordProfile.keylen, passwordProfile.digest);
var salt = site + login + passwordProfile.counter.toString(16);
return pbkdf2(masterPassword, salt, passwordProfile.iterations, passwordProfile.keylen, passwordProfile.digest);
}

var characterSubsets = {
lowercase: 'abcdefghijklmnopqrstuvwxyz',
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
numbers: '0123456789',
symbols: '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
lowercase: 'abcdefghijklmnopqrstuvwxyz',
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
numbers: '0123456789',
symbols: '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
};

function getSetOfCharacters(rules) {
if (typeof rules === 'undefined') {
return characterSubsets.lowercase + characterSubsets.uppercase + characterSubsets.numbers + characterSubsets.symbols;
}
var setOfChars = '';
rules.forEach(function (rule) {
setOfChars += characterSubsets[rule];
});
return setOfChars;
if (typeof rules === 'undefined') {
return characterSubsets.lowercase + characterSubsets.uppercase + characterSubsets.numbers + characterSubsets.symbols;
}
var setOfChars = '';
rules.forEach(function(rule) {
setOfChars += characterSubsets[rule];
});
return setOfChars;
}

function consumeEntropy(generatedPassword, quotient, setOfCharacters, maxLength) {
if (generatedPassword.length >= maxLength) {
return {value: generatedPassword, entropy: quotient};
}
var longDivision = quotient.divmod(setOfCharacters.length);
generatedPassword += setOfCharacters[longDivision.remainder];
return consumeEntropy(generatedPassword, longDivision.quotient, setOfCharacters, maxLength);
if (generatedPassword.length >= maxLength) {
return {value: generatedPassword, entropy: quotient};
}
var longDivision = quotient.divmod(setOfCharacters.length);
generatedPassword += setOfCharacters[longDivision.remainder];
return consumeEntropy(generatedPassword, longDivision.quotient, setOfCharacters, maxLength);
}

function insertStringPseudoRandomly(generatedPassword, entropy, string) {
for (var i = 0; i < string.length; i++) {
var longDivision = entropy.divmod(generatedPassword.length);
generatedPassword = generatedPassword.slice(0, longDivision.remainder) + string[i] + generatedPassword.slice(longDivision.remainder);
entropy = longDivision.quotient;
}
return generatedPassword;
for (var i = 0; i < string.length; i++) {
var longDivision = entropy.divmod(generatedPassword.length);
generatedPassword = generatedPassword.slice(0, longDivision.remainder) + string[i] + generatedPassword.slice(longDivision.remainder);
entropy = longDivision.quotient;
}
return generatedPassword;
}

function getOneCharPerRule(entropy, rules) {
var oneCharPerRules = '';
rules.forEach(function (rule) {
var password = consumeEntropy('', entropy, characterSubsets[rule], 1);
oneCharPerRules += password.value;
entropy = password.entropy;
});
return {value: oneCharPerRules, entropy: entropy};
var oneCharPerRules = '';
rules.forEach(function(rule) {
var password = consumeEntropy('', entropy, characterSubsets[rule], 1);
oneCharPerRules += password.value;
entropy = password.entropy;
});
return {value: oneCharPerRules, entropy: entropy};
}

function getConfiguredRules(passwordProfile) {
return ['lowercase', 'uppercase', 'numbers', 'symbols'].filter(function (rule) {
return passwordProfile[rule];
});
return ['lowercase', 'uppercase', 'numbers', 'symbols'].filter(function(rule) {
return passwordProfile[rule];
});
}

function renderPassword(entropy, passwordProfile) {
var rules = getConfiguredRules(passwordProfile);
var setOfCharacters = getSetOfCharacters(rules);
var password = consumeEntropy('', bigInt(entropy, 16), setOfCharacters, passwordProfile.length - rules.length);
var charactersToAdd = getOneCharPerRule(password.entropy, rules);
return insertStringPseudoRandomly(password.value, charactersToAdd.entropy, charactersToAdd.value);
var rules = getConfiguredRules(passwordProfile);
var setOfCharacters = getSetOfCharacters(rules);
var password = consumeEntropy('', bigInt(entropy, 16), setOfCharacters, passwordProfile.length - rules.length);
var charactersToAdd = getOneCharPerRule(password.entropy, rules);
return insertStringPseudoRandomly(password.value, charactersToAdd.entropy, charactersToAdd.value);
}

+ 28
- 28
tests/karma.config.js View File

@@ -1,29 +1,29 @@
module.exports = function (config) {
var configuration = {
basePath: '..',
frameworks: ['mocha', 'chai'],
files: [
'node_modules/big-integer/BigInteger.min.js',
'dist/lesspass.js',
'tests/**/*.js'
],
exclude: [
'tests/node.js',
'tests/helper.js',
'tests/karma.webcrypto.config.js',
],
preprocessors: {},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome', 'Firefox'],
singleRun: true,
concurrency: Infinity
};
if (process.env.TRAVIS) {
configuration.browsers = ['PhantomJS'];
}
config.set(configuration)
module.exports = function(config) {
var configuration = {
basePath: '..',
frameworks: ['mocha', 'chai'],
files: [
'node_modules/big-integer/BigInteger.min.js',
'dist/lesspass.js',
'tests/**/*.js'
],
exclude: [
'tests/node.js',
'tests/helper.js',
'tests/karma.webcrypto.config.js',
],
preprocessors: {},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome', 'Firefox'],
singleRun: true,
concurrency: Infinity
};
if (process.env.TRAVIS) {
configuration.browsers = ['PhantomJS'];
}
config.set(configuration)
};

+ 14
- 14
tests/node.js View File

@@ -5,19 +5,19 @@ const site = 'lesspass.com';
const login = 'contact@lesspass.com';
const masterPassword = 'password';
const passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
length: 16,
counter: 1,
version: 2
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
length: 16,
counter: 1,
version: 2
};
LessPass.generatePassword(site, login, masterPassword, passwordProfile)
.then(function (generatedPassword) {
assert.equal(generatedPassword, '\\g-A1-.OHEwrXjT#');
console.log('generated password ok');
})
.catch(function (e) {
console.log(e);
});
.then(function(generatedPassword) {
assert.equal(generatedPassword, '\\g-A1-.OHEwrXjT#');
console.log('generated password ok');
})
.catch(function(e) {
console.log(e);
});

+ 7
- 7
tests/pbkdf2.tests.js View File

@@ -1,13 +1,13 @@
var assert = chai.assert;

describe('LessPass', function () {
describe('pbkdf2', function () {
it('should secret, salt, 2, 32, sha256', function () {
return LessPass.pbkdf2('secret', 'salt', 2, 32, 'sha256').then(function (key) {
assert.equal('f92f45f9df4c2aeabae1ed3c16f7b64660c1f8e377fa9b4699b23c2c3a29f569', key);
})
});
describe('LessPass', function() {
describe('pbkdf2', function() {
it('should secret, salt, 2, 32, sha256', function() {
return LessPass.pbkdf2('secret', 'salt', 2, 32, 'sha256').then(function(key) {
assert.equal('f92f45f9df4c2aeabae1ed3c16f7b64660c1f8e377fa9b4699b23c2c3a29f569', key);
})
});
});
});




+ 535
- 574
tests/v1/api.tests.js
File diff suppressed because it is too large
View File


+ 79
- 79
tests/v1/deriveEncryptedLogin.tests.js View File

@@ -1,84 +1,84 @@
var assert = chai.assert;

describe('LessPass v1', function () {
describe('deriveEncryptedLogin', function () {
it('should createHmac', function () {
var encryptedLogin = '9f505f3a95fe0485da3242cb81c9fe25c2f400d8399737655a8dad2b52778d88';
var salt = 'lesspass.com1';
return LessPass._createHmac(encryptedLogin, salt).then(function (hmac) {
assert.equal('be00f942fc8aa67d8e76fc2456862b9d66d166ebfdd3dc2f0116e278209532ed', hmac);
});
});
it('should derive encrypted login with default options 1', function () {
const encryptedLogin = '90cff82b8847525370a8f29a59ecf45db62c719a535788ad0df58d32304e925d';
const site = 'lesspass.com';
return LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function (generatedPassword) {
assert.equal('ecd16aefc7e5', generatedPassword);
});
});
it('should derive encrypted login with default options 2', function () {
const encryptedLogin = '90cff82b8847525370a8f29a59ecf45db62c719a535788ad0df58d32304e925d';
const site = 'lesspass.com';
const option = {
counter: 1,
length: 12,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option).then(function (generatedPassword) {
assert.equal('ecd16aefc7e5', generatedPassword);
});
});
it('should derive encrypted login with defined length', function () {
var encryptedLogin = 'd79d8482f708122288af7b259393a58fe05840f4555cc935cdd3f062b9aa75ed';
var site = 'lesspass.com';
var option = {
counter: 1,
length: 10,
};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option).then(function (generatedPassword) {
assert.equal(10, generatedPassword.length);
});
});
it('should return two different passwords if site different 1', function () {
const encryptedLogin = 'f4fd3885fb70085f2285c3382e2d9adb4c2553285fc45dd896791aa5e79070a9';
const site = 'google.com';
return LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function (derivedEncryptedLogin) {
assert.equal('a957c3a459ec', derivedEncryptedLogin)
});
});
it('should return two different passwords if site different 2', function () {
const encryptedLogin = 'f4fd3885fb70085f2285c3382e2d9adb4c2553285fc45dd896791aa5e79070a9';
const site = 'facebook.com';
return LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function (derivedEncryptedLogin) {
assert.equal('d9f3a918c34b', derivedEncryptedLogin)
});
});
it('should return two different passwords if counter different 1', function () {
const encryptedLogin = 'dfba06278c9aa24d992bc2d390a53efef482788859455875f72015335d085fcd';
const site = 'lesspass.com';
const option = {counter: 1};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option).then(function (derivedEncryptedLogins) {
assert.equal('bb2e0b34036d', derivedEncryptedLogins)
});
});
it('should return two different passwords if counter different 2', function () {
const encryptedLogin = 'dfba06278c9aa24d992bc2d390a53efef482788859455875f72015335d085fcd';
const site = 'lesspass.com';
const option2 = {counter: 2};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option2).then(function (derivedEncryptedLogins) {
assert.equal('67fe8c05a248', derivedEncryptedLogins)
});
});
it('should derive encrypted login with sha 256', function () {
const encryptedLogin = '9f505f3a95fe0485da3242cb81c9fe25c2f400d8399737655a8dad2b52778d88';
const site = 'lesspass.com';
LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function (encryptedLogin) {
assert.equal('be00f942fc8a', encryptedLogin);
});
});
describe('LessPass v1', function() {
describe('deriveEncryptedLogin', function() {
it('should createHmac', function() {
var encryptedLogin = '9f505f3a95fe0485da3242cb81c9fe25c2f400d8399737655a8dad2b52778d88';
var salt = 'lesspass.com1';
return LessPass._createHmac(encryptedLogin, salt).then(function(hmac) {
assert.equal('be00f942fc8aa67d8e76fc2456862b9d66d166ebfdd3dc2f0116e278209532ed', hmac);
});
});
it('should derive encrypted login with default options 1', function() {
const encryptedLogin = '90cff82b8847525370a8f29a59ecf45db62c719a535788ad0df58d32304e925d';
const site = 'lesspass.com';
return LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function(generatedPassword) {
assert.equal('ecd16aefc7e5', generatedPassword);
});
});
it('should derive encrypted login with default options 2', function() {
const encryptedLogin = '90cff82b8847525370a8f29a59ecf45db62c719a535788ad0df58d32304e925d';
const site = 'lesspass.com';
const option = {
counter: 1,
length: 12,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option).then(function(generatedPassword) {
assert.equal('ecd16aefc7e5', generatedPassword);
});
});
it('should derive encrypted login with defined length', function() {
var encryptedLogin = 'd79d8482f708122288af7b259393a58fe05840f4555cc935cdd3f062b9aa75ed';
var site = 'lesspass.com';
var option = {
counter: 1,
length: 10,
};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option).then(function(generatedPassword) {
assert.equal(10, generatedPassword.length);
});
});
it('should return two different passwords if site different 1', function() {
const encryptedLogin = 'f4fd3885fb70085f2285c3382e2d9adb4c2553285fc45dd896791aa5e79070a9';
const site = 'google.com';
return LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function(derivedEncryptedLogin) {
assert.equal('a957c3a459ec', derivedEncryptedLogin)
});
});
it('should return two different passwords if site different 2', function() {
const encryptedLogin = 'f4fd3885fb70085f2285c3382e2d9adb4c2553285fc45dd896791aa5e79070a9';
const site = 'facebook.com';
return LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function(derivedEncryptedLogin) {
assert.equal('d9f3a918c34b', derivedEncryptedLogin)
});
});
it('should return two different passwords if counter different 1', function() {
const encryptedLogin = 'dfba06278c9aa24d992bc2d390a53efef482788859455875f72015335d085fcd';
const site = 'lesspass.com';
const option = {counter: 1};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option).then(function(derivedEncryptedLogins) {
assert.equal('bb2e0b34036d', derivedEncryptedLogins)
});
});
it('should return two different passwords if counter different 2', function() {
const encryptedLogin = 'dfba06278c9aa24d992bc2d390a53efef482788859455875f72015335d085fcd';
const site = 'lesspass.com';
const option2 = {counter: 2};
return LessPass._deriveEncryptedLogin(encryptedLogin, site, option2).then(function(derivedEncryptedLogins) {
assert.equal('67fe8c05a248', derivedEncryptedLogins)
});
});
it('should derive encrypted login with sha 256', function() {
const encryptedLogin = '9f505f3a95fe0485da3242cb81c9fe25c2f400d8399737655a8dad2b52778d88';
const site = 'lesspass.com';
LessPass._deriveEncryptedLogin(encryptedLogin, site).then(function(encryptedLogin) {
assert.equal('be00f942fc8a', encryptedLogin);
});
});
});
});


+ 58
- 58
tests/v1/getPasswordTemplate.tests.js View File

@@ -1,63 +1,63 @@
var assert = chai.assert;

describe('Lessass v1', function () {
describe('getPasswordTemplate', function () {
it('should get default template', function () {
assert.equal('vcVCns', LessPass._getPasswordTemplate({
counter: 1,
length: 12,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
}));
});
it('should get lowercase template', function () {
assert.equal('vc', LessPass._getPasswordTemplate({
lowercase: true,
uppercase: false,
numbers: false,
symbols: false
}));
});
it('should get uppercase template', function () {
assert.equal('VC', LessPass._getPasswordTemplate({
lowercase: false,
uppercase: true,
numbers: false,
symbols: false
}));
});
it('should get numbers template', function () {
assert.equal('n', LessPass._getPasswordTemplate({
lowercase: false,
uppercase: false,
numbers: true,
symbols: false
}));
});
it('should get symbols template', function () {
assert.equal('s', LessPass._getPasswordTemplate({
lowercase: false,
uppercase: false,
numbers: false,
symbols: true
}));
});
it('should concatenate template if two password settings', function () {
assert.equal('vcVC', LessPass._getPasswordTemplate({
lowercase: true,
uppercase: true,
numbers: false,
symbols: false
}));
assert.equal('vcns', LessPass._getPasswordTemplate({
lowercase: true,
uppercase: false,
numbers: true,
symbols: true
}));
});
describe('Lessass v1', function() {
describe('getPasswordTemplate', function() {
it('should get default template', function() {
assert.equal('vcVCns', LessPass._getPasswordTemplate({
counter: 1,
length: 12,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
}));
});
it('should get lowercase template', function() {
assert.equal('vc', LessPass._getPasswordTemplate({
lowercase: true,
uppercase: false,
numbers: false,
symbols: false
}));
});
it('should get uppercase template', function() {
assert.equal('VC', LessPass._getPasswordTemplate({
lowercase: false,
uppercase: true,
numbers: false,
symbols: false
}));
});
it('should get numbers template', function() {
assert.equal('n', LessPass._getPasswordTemplate({
lowercase: false,
uppercase: false,
numbers: true,
symbols: false
}));
});
it('should get symbols template', function() {
assert.equal('s', LessPass._getPasswordTemplate({
lowercase: false,
uppercase: false,
numbers: false,
symbols: true
}));
});
it('should concatenate template if two password settings', function() {
assert.equal('vcVC', LessPass._getPasswordTemplate({
lowercase: true,
uppercase: true,
numbers: false,
symbols: false
}));
assert.equal('vcns', LessPass._getPasswordTemplate({
lowercase: true,
uppercase: false,
numbers: true,
symbols: true
}));
});
});
});


+ 31
- 31
tests/v1/prettyPrint.js View File

@@ -1,35 +1,35 @@
var assert = chai.assert;

describe('LessPass v1', function () {
describe('prettyPrint', function () {
it('should print different password if templates different', function () {
var encryptedLogin = '78ae5892055ab59fdd54489ae30928d322841a27590b65cf875fcfdd083f7c32';
assert.notEqual(LessPass._prettyPrint(encryptedLogin, 'cv'), LessPass._prettyPrint(encryptedLogin, 'vc'));
});
it('must return a string of the same length as the input', function () {
var hash = 'f5785e569ab5d38b02e2248c798ac17df90f57a85f34a9d5382408c2f0d9532d';
assert.equal(hash.length, LessPass._prettyPrint(hash, 'cv').length);
});
it('should return char inside a string based on modulo of the index', function () {
var template = 'cv';
assert.equal('c', LessPass._getCharType(template, 0));
assert.equal('v', LessPass._getCharType(template, 1));
assert.equal('c', LessPass._getCharType(template, 10));
});
it('should convert a string into an array of char code', function () {
var charCodes = LessPass._string2charCodes('ab40f6ee71');
assert.equal(97, charCodes[0]);
assert.equal(98, charCodes[1]);
assert.equal(10, charCodes.length);
});
it('should get password char based on its type and index', function () {
var typeVowel = 'V';
assert.equal('A', LessPass._getPasswordChar(typeVowel, 0));
});
it('should modulo if overflow', function () {
var typeVowel = 'V';
assert.equal('E', LessPass._getPasswordChar(typeVowel, 1));
assert.equal('E', LessPass._getPasswordChar(typeVowel, 7));
});
describe('LessPass v1', function() {
describe('prettyPrint', function() {
it('should print different password if templates different', function() {
var encryptedLogin = '78ae5892055ab59fdd54489ae30928d322841a27590b65cf875fcfdd083f7c32';
assert.notEqual(LessPass._prettyPrint(encryptedLogin, 'cv'), LessPass._prettyPrint(encryptedLogin, 'vc'));
});
it('must return a string of the same length as the input', function() {
var hash = 'f5785e569ab5d38b02e2248c798ac17df90f57a85f34a9d5382408c2f0d9532d';
assert.equal(hash.length, LessPass._prettyPrint(hash, 'cv').length);
});
it('should return char inside a string based on modulo of the index', function() {
var template = 'cv';
assert.equal('c', LessPass._getCharType(template, 0));
assert.equal('v', LessPass._getCharType(template, 1));
assert.equal('c', LessPass._getCharType(template, 10));
});
it('should convert a string into an array of char code', function() {
var charCodes = LessPass._string2charCodes('ab40f6ee71');
assert.equal(97, charCodes[0]);
assert.equal(98, charCodes[1]);
assert.equal(10, charCodes.length);
});
it('should get password char based on its type and index', function() {
var typeVowel = 'V';
assert.equal('A', LessPass._getPasswordChar(typeVowel, 0));
});
it('should modulo if overflow', function() {
var typeVowel = 'V';
assert.equal('E', LessPass._getPasswordChar(typeVowel, 1));
assert.equal('E', LessPass._getPasswordChar(typeVowel, 7));
});
});
});

+ 74
- 74
tests/v2/api.tests.js View File

@@ -1,79 +1,79 @@
var assert = chai.assert;

describe('LessPass v2', function () {
describe('API', function () {
it('render password', function () {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
length: 16,
counter: 1,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function (generatedPassword) {
assert.equal('WHLpUL)e00[iHR+w', generatedPassword);
});
});
it('render password no symbols', function () {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: false,
length: 14,
counter: 2,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function (generatedPassword) {
assert.equal('MBAsB7b1Prt8Sl', generatedPassword);
});
});
it('render password only digit', function () {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: false,
uppercase: false,
numbers: true,
symbols: false,
length: 6,
counter: 3,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function (generatedPassword) {
assert.equal('117843', generatedPassword);
});
});
it('render password no number', function () {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: true,
uppercase: true,
numbers: false,
symbols: true,
length: 14,
counter: 1,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function (generatedPassword) {
assert.equal("sB>{qF}wN%/-fm", generatedPassword);
});
});
describe('LessPass v2', function() {
describe('API', function() {
it('render password', function() {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
length: 16,
counter: 1,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function(generatedPassword) {
assert.equal('WHLpUL)e00[iHR+w', generatedPassword);
});
});
it('render password no symbols', function() {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: true,
uppercase: true,
numbers: true,
symbols: false,
length: 14,
counter: 2,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function(generatedPassword) {
assert.equal('MBAsB7b1Prt8Sl', generatedPassword);
});
});
it('render password only digit', function() {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: false,
uppercase: false,
numbers: true,
symbols: false,
length: 6,
counter: 3,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function(generatedPassword) {
assert.equal('117843', generatedPassword);
});
});
it('render password no number', function() {
this.timeout(10000);
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile = {
lowercase: true,
uppercase: true,
numbers: false,
symbols: true,
length: 14,
counter: 1,
version: 2
};
return LessPass.generatePassword(site, login, masterPassword, passwordProfile).then(function(generatedPassword) {
assert.equal("sB>{qF}wN%/-fm", generatedPassword);
});
});
});
});


+ 54
- 54
tests/v2/entropy.tests.js View File

@@ -1,58 +1,58 @@
var assert = chai.assert;

describe('LessPass v2', 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 = {
iterations: 100000,
keylen: 32,
digest: 'sha256',
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 1', function () {
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile1 = {iterations: 1, keylen: 16, digest: 'sha256', counter: 1};
return LessPass._calcEntropy(site, login, masterPassword, passwordProfile1).then(function (entropy) {
assert.equal('d3ec1e988dd0b3640c7491cd2c2a88b5', entropy)
});
});
it('calc entropy different if counter different 2', function () {
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile2 = {iterations: 1, keylen: 16, digest: 'sha256', counter: 2};
return LessPass._calcEntropy(site, login, masterPassword, passwordProfile2).then(function (entropy) {
assert.equal('ddfb1136260f930c21f6d72f6eddbd40', entropy)
});
});
it('consume entropy', function () {
var password = LessPass._consumeEntropy('', bigInt(4 * 4 + 2), "abcd", 2);
assert.equal('ca', password.value);
assert.equal(1, password.entropy)
});
describe('LessPass v2', 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 = {
iterations: 100000,
keylen: 32,
digest: 'sha256',
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 1', function() {
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile1 = {iterations: 1, keylen: 16, digest: 'sha256', counter: 1};
return LessPass._calcEntropy(site, login, masterPassword, passwordProfile1).then(function(entropy) {
assert.equal('d3ec1e988dd0b3640c7491cd2c2a88b5', entropy)
});
});
it('calc entropy different if counter different 2', function() {
var site = 'example.org';
var login = 'contact@example.org';
var masterPassword = 'password';
var passwordProfile2 = {iterations: 1, keylen: 16, digest: 'sha256', counter: 2};
return LessPass._calcEntropy(site, login, masterPassword, passwordProfile2).then(function(entropy) {
assert.equal('ddfb1136260f930c21f6d72f6eddbd40', entropy)
});
});
it('consume entropy', function() {
var password = LessPass._consumeEntropy('', bigInt(4 * 4 + 2), "abcd", 2);
assert.equal('ca', password.value);
assert.equal(1, password.entropy)
});
});
});

+ 67
- 67
tests/v2/renderPassword.tests.js View File

@@ -1,70 +1,70 @@
var assert = chai.assert;

describe('LessPass v2', function () {
var defaultPasswordProfile = {
length: 16,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
describe('LessPass v2', function() {
var defaultPasswordProfile = {
length: 16,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
};
it('render password use remainder of long division beetween entropy and set of chars length as an index', function() {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
assert.equal('W', LessPass._renderPassword(entropy, defaultPasswordProfile)[0]);
});
it('render password use quotient as second entropy recursively', function() {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
assert.equal('H', LessPass._renderPassword(entropy, defaultPasswordProfile)[1]);
});
it('render password has default length of 16', function() {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
assert.equal(16, LessPass._renderPassword(entropy, defaultPasswordProfile).length);
});
it('render password can specify length', function() {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
var passwordProfile = {
length: 20,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
};
it('render password use remainder of long division beetween entropy and set of chars length as an index', function () {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
assert.equal('W', LessPass._renderPassword(entropy, defaultPasswordProfile)[0]);
});
it('render password use quotient as second entropy recursively', function () {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
assert.equal('H', LessPass._renderPassword(entropy, defaultPasswordProfile)[1]);
});
it('render password has default length of 16', function () {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
assert.equal(16, LessPass._renderPassword(entropy, defaultPasswordProfile).length);
});
it('render password can specify length', function () {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
var passwordProfile = {
length: 20,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
};
assert.equal(20, LessPass._renderPassword(entropy, passwordProfile).length);
});
it('include one char per set of characters', function () {
var password = LessPass._insertStringPseudoRandomly('123456', bigInt(7 * 6 + 2), 'uT');
assert.equal('T12u3456', password);
});
it('render password return at least one char in every characters set', function () {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
var passwordProfile = {
length: 6,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
};
var generatedPassword = LessPass._renderPassword(entropy, passwordProfile);
var passwordLength = generatedPassword.length;
var lowercaseOk = false;
var uppercaseOk = false;
var numbersOk = false;
var symbolsOk = false;
while (passwordLength--) {
if ('abcdefghijklmnopqrstuvwxyz'.indexOf(generatedPassword[passwordLength]) !== -1) {
lowercaseOk = true;
}
if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.indexOf(generatedPassword[passwordLength]) !== -1) {
uppercaseOk = true;
}
if ('0123456789'.indexOf(generatedPassword[passwordLength]) !== -1) {
numbersOk = true;
}
if ('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'.indexOf(generatedPassword[passwordLength]) !== -1) {
symbolsOk = true;
}
}
assert.equal(6, generatedPassword.length);
assert(lowercaseOk && uppercaseOk && numbersOk && symbolsOk, 'there is no at least one char in every characters set');
});
});
assert.equal(20, LessPass._renderPassword(entropy, passwordProfile).length);
});
it('include one char per set of characters', function() {
var password = LessPass._insertStringPseudoRandomly('123456', bigInt(7 * 6 + 2), 'uT');
assert.equal('T12u3456', password);
});
it('render password return at least one char in every characters set', function() {
var entropy = 'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e';
var passwordProfile = {
length: 6,
lowercase: true,
uppercase: true,
numbers: true,
symbols: true,
};
var generatedPassword = LessPass._renderPassword(entropy, passwordProfile);
var passwordLength = generatedPassword.length;
var lowercaseOk = false;
var uppercaseOk = false;
var numbersOk = false;
var symbolsOk = false;
while (passwordLength--) {
if ('abcdefghijklmnopqrstuvwxyz'.indexOf(generatedPassword[passwordLength]) !== -1) {
lowercaseOk = true;
}
if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.indexOf(generatedPassword[passwordLength]) !== -1) {
uppercaseOk = true;
}
if ('0123456789'.indexOf(generatedPassword[passwordLength]) !== -1) {
numbersOk = true;
}
if ('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'.indexOf(generatedPassword[passwordLength]) !== -1) {
symbolsOk = true;
}
}
assert.equal(6, generatedPassword.length);
assert(lowercaseOk && uppercaseOk && numbersOk && symbolsOk, 'there is no at least one char in every characters set');
});
});

+ 55
- 55
tests/v2/setOfCharacters.tests.js View File

@@ -1,59 +1,59 @@
var assert = chai.assert;

describe('LessPass v2', function () {
describe('set of characters', function () {
it('get default set of characters', function () {
var setOfCharacters = LessPass._getSetOfCharacters();
assert.equal(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~',
setOfCharacters
);
assert.equal(26 * 2 + 10 + 32, setOfCharacters.length);
});
it('get default set of characters concat rules in order', function () {
var setOfCharacters = LessPass._getSetOfCharacters(['lowercase', 'uppercase', 'numbers']);
assert.equal('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', setOfCharacters);
assert.equal(26 * 2 + 10, setOfCharacters.length);
});
it('get set of characters only lowercase', function () {
var setOfCharacters = LessPass._getSetOfCharacters(['lowercase']);
assert.equal('abcdefghijklmnopqrstuvwxyz', setOfCharacters);
assert.equal(26, setOfCharacters.length);
});
it('get set of characters only uppercase', function () {
var setOfCharacters = LessPass._getSetOfCharacters(['uppercase']);
assert.equal('ABCDEFGHIJKLMNOPQRSTUVWXYZ', setOfCharacters);
assert.equal(26, setOfCharacters.length);
});
it('get set of characters only numbers', function () {
var setOfCharacters = LessPass._getSetOfCharacters(['numbers']);
assert.equal('0123456789', setOfCharacters);
assert.equal(10, setOfCharacters.length);
});
it('get set of characters only symbols', function () {
var setOfCharacters = LessPass._getSetOfCharacters(['symbols']);
assert.equal('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', setOfCharacters);
assert.equal(32, setOfCharacters.length);
});
it('generate one char per rules', function () {
var oneCharPerSetOfCharacters = LessPass._getOneCharPerRule(
bigInt(26 * 26),
['lowercase', 'uppercase']
);
assert.equal('aA', oneCharPerSetOfCharacters.value);
assert.equal(2, oneCharPerSetOfCharacters.value.length);
assert.equal(1, oneCharPerSetOfCharacters.entropy);
});
it('configured rules', function () {
assert.deepEqual(['uppercase'], LessPass._getConfiguredRules({uppercase: true}));
assert.deepEqual(['lowercase', 'uppercase'], LessPass._getConfiguredRules({uppercase: true, lowercase: true}));
assert.deepEqual(['lowercase'], LessPass._getConfiguredRules({lowercase: true, symbols: false}));
assert.deepEqual(['lowercase', 'uppercase', 'numbers', 'symbols'], LessPass._getConfiguredRules({
lowercase: true,
uppercase: true,
symbols: true,
numbers: true
}));
});
describe('LessPass v2', function() {
describe('set of characters', function() {
it('get default set of characters', function() {
var setOfCharacters = LessPass._getSetOfCharacters();
assert.equal(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~',
setOfCharacters
);
assert.equal(26 * 2 + 10 + 32, setOfCharacters.length);
});
it('get default set of characters concat rules in order', function() {
var setOfCharacters = LessPass._getSetOfCharacters(['lowercase', 'uppercase', 'numbers']);
assert.equal('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', setOfCharacters);
assert.equal(26 * 2 + 10, setOfCharacters.length);
});
it('get set of characters only lowercase', function() {
var setOfCharacters = LessPass._getSetOfCharacters(['lowercase']);
assert.equal('abcdefghijklmnopqrstuvwxyz', setOfCharacters);
assert.equal(26, setOfCharacters.length);
});
it('get set of characters only uppercase', function() {
var setOfCharacters = LessPass._getSetOfCharacters(['uppercase']);
assert.equal('ABCDEFGHIJKLMNOPQRSTUVWXYZ', setOfCharacters);
assert.equal(26, setOfCharacters.length);
});
it('get set of characters only numbers', function() {
var setOfCharacters = LessPass._getSetOfCharacters(['numbers']);
assert.equal('0123456789', setOfCharacters);
assert.equal(10, setOfCharacters.length);
});
it('get set of characters only symbols', function() {
var setOfCharacters = LessPass._getSetOfCharacters(['symbols']);
assert.equal('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', setOfCharacters);
assert.equal(32, setOfCharacters.length);
});
it('generate one char per rules', function() {
var oneCharPerSetOfCharacters = LessPass._getOneCharPerRule(
bigInt(26 * 26),
['lowercase', 'uppercase']
);
assert.equal('aA', oneCharPerSetOfCharacters.value);
assert.equal(2, oneCharPerSetOfCharacters.value.length);
assert.equal(1, oneCharPerSetOfCharacters.entropy);
});
it('configured rules', function() {
assert.deepEqual(['uppercase'], LessPass._getConfiguredRules({uppercase: true}));
assert.deepEqual(['lowercase', 'uppercase'], LessPass._getConfiguredRules({uppercase: true, lowercase: true}));
assert.deepEqual(['lowercase'], LessPass._getConfiguredRules({lowercase: true, symbols: false}));
assert.deepEqual(['lowercase', 'uppercase', 'numbers', 'symbols'], LessPass._getConfiguredRules({
lowercase: true,
uppercase: true,
symbols: true,
numbers: true
}));
});
});
});

+ 19
- 19
webpack.config.js View File

@@ -4,22 +4,22 @@ var webpack = require('webpack');
var production = process.env.NODE_ENV === 'production' || false;

module.exports = {
entry: './src/lesspass.js',
output: {
filename: production ? 'lesspass.min.js' : 'lesspass.js',
path: path.resolve(__dirname, 'dist'),
library: 'LessPass',
libraryTarget: 'umd'
},
module: {
rules: [
{test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}
]
},
plugins: production ? [
new webpack.optimize.UglifyJsPlugin({
beautify: false,
comments: false
})
] : []
};
entry: './src/lesspass.js',
output: {
filename: production ? 'lesspass.min.js' : 'lesspass.js',
path: path.resolve(__dirname, 'dist'),
library: 'LessPass',
libraryTarget: 'umd'
},
module: {
rules: [
{test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}
]
},
plugins: production ? [
new webpack.optimize.UglifyJsPlugin({
beautify: false,
comments: false
})
] : []
};

Loading…
Cancel
Save