strict-password-generator
Version:
Generate a random password with strict requirements
134 lines (110 loc) • 6.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _crypto = require('crypto');
var _crypto2 = _interopRequireDefault(_crypto);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _debug = require('debug');
var _debug2 = _interopRequireDefault(_debug);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var debug = new _debug2.default('src:PasswordGenerator:');
var PasswordGenerator = function () {
function PasswordGenerator() {
_classCallCheck(this, PasswordGenerator);
}
_createClass(PasswordGenerator, [{
key: 'generateRandomNumber',
value: function generateRandomNumber() {
var maximumValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;
var minimumValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var retry = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
debug('Input values to number generator... Max: ', maximumValue, 'Min: ', minimumValue, 'retry: ', retry);
if (retry >= 1000) {
// if number generation fails 1000 times in a row throw error
throw new Error('Password Generation Failed. Max 1000 attempts exceeded');
}
if (minimumValue > maximumValue) {
throw new Error('minimumValue cannot be greater than maximumValue');
}
if (minimumValue === maximumValue) return maximumValue;
var rand = _crypto2.default.randomBytes(256)[0] % maximumValue;
if (rand < minimumValue && rand + minimumValue >= maximumValue) {
// if true, rand does not meet given criteria and must be regenerated
return this.generateRandomNumber(maximumValue, minimumValue, retry++);
} else if (rand < minimumValue) return rand + minimumValue;
return rand;
}
}, {
key: 'generateSpecialCharacter',
value: function generateSpecialCharacter() {
var chars = ['!', '@', '#', '$', '%', '^', '*', '+', '_', '-', '=', ':', ';', '?'];
return chars[this.generateRandomNumber(chars.length)];
}
}, {
key: 'generateLowerCaseAlpha',
value: function generateLowerCaseAlpha() {
var alpha = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
return alpha[this.generateRandomNumber(alpha.length)];
}
}, {
key: 'generateUpperCaseAlpha',
value: function generateUpperCaseAlpha() {
return this.generateLowerCaseAlpha().toUpperCase();
}
}, {
key: 'generatePassword',
value: function generatePassword(options) {
var _this = this;
if (options === undefined) options = {};
if (options.minimumLength < 4) throw new Error('Error: minimumLength must be greater than or equal to 4');
if (!options.hasOwnProperty('upperCaseAlpha')) options.upperCaseAlpha = true; // default
if (!options.hasOwnProperty('lowerCaseAlpha')) options.lowerCaseAlpha = true; // default
if (!options.hasOwnProperty('specialCharacter')) options.specialCharacter = true; // default
if (!options.hasOwnProperty('number')) options.number = true; // default
if (!options.hasOwnProperty('minimumLength')) options.minimumLength = 8; // default
if (!options.hasOwnProperty('maximumLength')) options.maximumLength = options.minimumLength + 4; // default
if (!options.hasOwnProperty('exactLength')) {
// if no exactLength is specified, password length will be between minimiumLength and maximumLength (inclusive)
debug('Password length generation result: ');
options.exactLength = this.generateRandomNumber(options.maximumLength + 1, options.minimumLength); // add one to maximumLength to ensure inclusivity
debug(options.exactLength);
}
var password = [];
var requirements = {};
options.upperCaseAlpha ? requirements.upperCaseAlpha = this.generateUpperCaseAlpha() : requirements.upperCaseAlpha = false;
options.lowerCaseAlpha ? requirements.lowerCaseAlpha = this.generateLowerCaseAlpha() : requirements.lowerCaseAlpha = false;
options.specialCharacter ? requirements.specialCharacter = this.generateSpecialCharacter() : requirements.specialCharacter = false;
options.number ? requirements.number = this.generateRandomNumber() : requirements.number = false;
_lodash2.default.forEach(requirements, function (value, key) {
if (value === false) return;
var requirementMet = false;
while (!requirementMet) {
debug('Generate index to place requirement. Length of password: ', options.exactLength);
var rand = _this.generateRandomNumber(options.exactLength); // position between 0 and length of password - 1
debug('Index generated: ', rand);
if (password[rand] === undefined) {
password[rand] = value;
requirementMet = true;
}
}
});
for (var i = 0; i < options.exactLength; i++) {
var possibleCharacters = [];
if (options.upperCaseAlpha) possibleCharacters.push(this.generateUpperCaseAlpha());
if (options.lowerCaseAlpha) possibleCharacters.push(this.generateLowerCaseAlpha());
if (options.specialCharacter) possibleCharacters.push(this.generateSpecialCharacter());
if (options.number) possibleCharacters.push(this.generateRandomNumber());
if (password[i] === undefined) {
password[i] = possibleCharacters[this.generateRandomNumber(possibleCharacters.length)];
}
}
return password.join('');
}
}]);
return PasswordGenerator;
}();
exports.default = PasswordGenerator;