Pārlūkot izejas kodu

add pbkdf2 polyfill

pull/342/head
Guillaume Vincent pirms 8 gadiem
vecāks
revīzija
1aa19da4ab
7 mainītis faili ar 155 papildinājumiem un 46 dzēšanām
  1. +3
    -0
      index.js
  2. +75
    -29
      lib/lesspass.js
  3. +51
    -0
      src/pbkdf2.js
  4. +6
    -15
      src/v2.js
  5. +1
    -1
      tests/helper.js
  6. +3
    -1
      tests/karma.config.js
  7. +16
    -0
      tests/pbkdf2.tests.js

+ 3
- 0
index.js Parādīt failu

@@ -1,5 +1,6 @@
var v1 = require('./src/v1');
var v2 = require('./src/v2');
var pbkdf2 = require('./src/pbkdf2');

module.exports = {
encryptLogin: v1.encryptLogin,
@@ -21,4 +22,6 @@ module.exports = {
_insertStringPseudoRandomly: v2._insertStringPseudoRandomly,
_getOneCharPerRule: v2._getOneCharPerRule,
_renderPassword: v2._renderPassword,

pbkdf2: pbkdf2
};

+ 75
- 29
lib/lesspass.js Parādīt failu

@@ -1,6 +1,7 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.LessPass = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var v1 = require('./src/v1');
var v2 = require('./src/v2');
var pbkdf2 = require('./src/pbkdf2');

module.exports = {
encryptLogin: v1.encryptLogin,
@@ -18,12 +19,14 @@ module.exports = {
_calcEntropy: v2._calcEntropy,
_consumeEntropy: v2._consumeEntropy,
_getSetOfCharacters: v2._getSetOfCharacters,
_validRules: v2._validRules,
_getConfiguredRules: v2._getConfiguredRules,
_insertStringPseudoRandomly: v2._insertStringPseudoRandomly,
_getOneCharPerRule: v2._getOneCharPerRule,
_renderPassword: v2._renderPassword,

pbkdf2: pbkdf2
};
},{"./src/v1":47,"./src/v2":48}],2:[function(require,module,exports){
},{"./src/pbkdf2":47,"./src/v1":48,"./src/v2":49}],2:[function(require,module,exports){
'use strict'

exports.byteLength = byteLength
@@ -13535,6 +13538,58 @@ function config (name) {

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],47:[function(require,module,exports){
var pbkdf2 = require('pbkdf2');
var Promise = require("bluebird");


function shouldUseNative() {
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', Unibabel.utf8ToBuffer(password), 'PBKDF2', false, ['deriveKey'])
.then(function (key) {
var algo = {
name: 'PBKDF2',
salt: Unibabel.utf8ToBuffer(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 (keyArrayBuffer) {
return Unibabel.bufferToHex(new Uint8Array(keyArrayBuffer));
});
});
}

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'));
}
});
});
}


module.exports = shouldUseNative() ? pbkdf2Native : pbkdf2Browserified;
},{"bluebird":4,"pbkdf2":20}],48:[function(require,module,exports){
(function (Buffer){
var pbkdf2 = require('pbkdf2');
var createHMAC = require('create-hmac');
@@ -13658,9 +13713,8 @@ function createFingerprint(str) {
});
}
}).call(this,require("buffer").Buffer)
},{"bluebird":4,"buffer":7,"create-hmac":13,"pbkdf2":20}],48:[function(require,module,exports){
var Promise = require("bluebird");
var pbkdf2 = require('pbkdf2');
},{"bluebird":4,"buffer":7,"create-hmac":13,"pbkdf2":20}],49:[function(require,module,exports){
var pbkdf2 = require('./pbkdf2');
var bigInt = require("big-integer");
var objectAssign = require('object-assign');

@@ -13669,15 +13723,16 @@ module.exports = {
_calcEntropy: calcEntropy,
_consumeEntropy: consumeEntropy,
_getSetOfCharacters: getSetOfCharacters,
_validRules: validRules,
_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)
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
return calcEntropy(site, login, masterPassword, _passwordProfile).then(function (entropy) {
return renderPassword(entropy, _passwordProfile);
});
}

@@ -13687,27 +13742,18 @@ var defaultPasswordProfile = {
digits: true,
symbols: true,
length: 16,
counter: 1,
index: 1,
iterations: 100000,
keylen: 32,
digest: 'sha256'
};

function calcEntropy(site, login, masterPassword, passwordProfile) {
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
return new Promise(function (resolve, reject) {
var salt = site + login + _passwordProfile.counter.toString(16);
pbkdf2.pbkdf2(masterPassword, salt, _passwordProfile.iterations, _passwordProfile.keylen, _passwordProfile.digest, function (error, key) {
if (error) {
reject('error in pbkdf2');
} else {
resolve(key.toString('hex'));
}
});
});
var salt = site + login + passwordProfile.index.toString(16);
return pbkdf2(masterPassword, salt, passwordProfile.iterations, passwordProfile.keylen, passwordProfile.digest);
}

var subsetOfChars = {
var characterSubsets = {
lowercase: 'abcdefghijklmnopqrstuvwxyz',
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
digits: '0123456789',
@@ -13716,22 +13762,22 @@ var subsetOfChars = {

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

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

function insertStringPseudoRandomly(generatedPassword, entropy, string) {
@@ -13746,14 +13792,14 @@ function insertStringPseudoRandomly(generatedPassword, entropy, string) {
function getOneCharPerRule(entropy, rules) {
var oneCharPerRules = '';
rules.forEach(function (rule) {
var password = consumeEntropy('', entropy, subsetOfChars[rule], 1);
var password = consumeEntropy('', entropy, characterSubsets[rule], 1);
oneCharPerRules += password.value;
entropy = password.entropy;
});
return {value: oneCharPerRules, entropy: entropy};
}

function validRules(passwordProfile) {
function getConfiguredRules(passwordProfile) {
return ['lowercase', 'uppercase', 'digits', 'symbols'].filter(function (rule) {
return passwordProfile[rule];
});
@@ -13761,12 +13807,12 @@ function validRules(passwordProfile) {

function renderPassword(entropy, passwordProfile) {
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
var rules = validRules(_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);
}

},{"big-integer":3,"bluebird":4,"object-assign":19,"pbkdf2":20}]},{},[1])(1)
},{"./pbkdf2":47,"big-integer":3,"object-assign":19}]},{},[1])(1)
});

+ 51
- 0
src/pbkdf2.js Parādīt failu

@@ -0,0 +1,51 @@
var pbkdf2 = require('pbkdf2');
var Promise = require("bluebird");


function shouldUseNative() {
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', Unibabel.utf8ToBuffer(password), 'PBKDF2', false, ['deriveKey'])
.then(function (key) {
var algo = {
name: 'PBKDF2',
salt: Unibabel.utf8ToBuffer(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 (keyArrayBuffer) {
return Unibabel.bufferToHex(new Uint8Array(keyArrayBuffer));
});
});
}

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'));
}
});
});
}


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

+ 6
- 15
src/v2.js Parādīt failu

@@ -1,5 +1,4 @@
var Promise = require("bluebird");
var pbkdf2 = require('pbkdf2');
var pbkdf2 = require('./pbkdf2');
var bigInt = require("big-integer");
var objectAssign = require('object-assign');

@@ -15,8 +14,9 @@ module.exports = {
};

function generatePassword(site, login, masterPassword, passwordProfile) {
return calcEntropy(site, login, masterPassword, passwordProfile).then(function (entropy) {
return renderPassword(entropy, passwordProfile);
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
return calcEntropy(site, login, masterPassword, _passwordProfile).then(function (entropy) {
return renderPassword(entropy, _passwordProfile);
});
}

@@ -33,17 +33,8 @@ var defaultPasswordProfile = {
};

function calcEntropy(site, login, masterPassword, passwordProfile) {
var _passwordProfile = objectAssign({}, defaultPasswordProfile, passwordProfile);
return new Promise(function (resolve, reject) {
var salt = site + login + _passwordProfile.index.toString(16);
pbkdf2.pbkdf2(masterPassword, salt, _passwordProfile.iterations, _passwordProfile.keylen, _passwordProfile.digest, function (error, key) {
if (error) {
reject('error in pbkdf2');
} else {
resolve(key.toString('hex'));
}
});
});
var salt = site + login + passwordProfile.index.toString(16);
return pbkdf2(masterPassword, salt, passwordProfile.iterations, passwordProfile.keylen, passwordProfile.digest);
}

var characterSubsets = {


+ 1
- 1
tests/helper.js Parādīt failu

@@ -1,4 +1,4 @@
// globals
global.chai = require('chai');
global.LessPass = require('../index');
global.bigInt = require("big-integer");
global.bigInt = require("big-integer");

+ 3
- 1
tests/karma.config.js Parādīt failu

@@ -5,6 +5,8 @@ module.exports = function (config) {
files: [
'node_modules/bluebird/js/browser/bluebird.core.min.js',
'node_modules/big-integer/BigInteger.min.js',
'node_modules/unibabel/index.js',
'node_modules/unibabel/unibabel.hex.js',
'lib/lesspass.js',
'tests/**/*.js'
],
@@ -14,7 +16,7 @@ module.exports = function (config) {
'tests/karma.webcrypto.config.js',
],
preprocessors: {},
reporters: ['progress'],
reporters: ['spec'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,


+ 16
- 0
tests/pbkdf2.tests.js Parādīt failu

@@ -0,0 +1,16 @@
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);
})
});
});
});






Notiek ielāde…
Atcelt
Saglabāt