Генератор паролей Javascript с добавлением пробелов и неудачных тестов
Я пытаюсь создать генератор паролей, который создает пароли, соответствующие:
- Не менее 8 символов в длину, не более 40 символов в длину
- Должен содержать как минимум 1 заглавную, строчную букву, число и символ
Я избегаю Math.random по своему выбору, я предпочитаю опцию crypto.
Я прошел через множество статей, чтобы попытаться заставить это работать, но у меня есть следующие проблемы:
Случайные пробелы появляются в выходной строке, часто в конце.
Выходные значения иногда не соответствуют правилу min 8 char.
Я понимаю, что, возможно, у меня слишком много дополнительных операторов, если они дважды проверяют вещи, но я изо всех сил пытаюсь понять, в чем дело.
Это относится к другой системе, поэтому я создаю ее как можно более модульной и функциональной. Извинения за большой фрагмент ниже, я не мог заставить его работать в jsfiddle.
function cryptoPassword(){
var minFieldNum = 8; //Minimum char size of desired output
var maxFieldNum = 40; //X defines their fields as 40 as the max_length
var outputValue = ''; //Output for field/overall function
var fieldRandom = getRandomInt(minFieldNum, maxFieldNum); //Generate length of password
if (fieldRandom < minFieldNum || fieldRandom > maxFieldNum) {
fieldRandom = getRandomInt(minFieldNum, maxFieldNum); //Regenerate if length doesn't conform - Not working?
}
else {
for (i = 0; outputValue.length < fieldRandom; i++) {
var mask = getRandomMask(); //Get mask selection
var randomChar = mask.charAt(getRandomInt(0,mask.length)); //Pick random char in mask
if (randomChar == " ") { //I don't know where the spaces come from
var randomChar = mask.charAt(getRandomInt(0,mask.length)); //Pick random char in mask
}
outputValue += randomChar; //Add to output
}
if (passwordChecker(outputValue, minFieldNum)) {
return outputValue + " " + passwordChecker(outputValue, minFieldNum);
}
else {
return cryptoPassword();
}
}
}
function getRandomInt(min, max) {
var byteArray = new Uint8Array(1);
window.crypto.getRandomValues(byteArray);
var range = (max - min + 1);
return min + (byteArray[0] % range);
}
function getRandomMask() {
var maskLcaseChar = 'abcdefghijklmnopqrstuvwxyz';
var maskUcaseChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var maskNumeric = '0123456789';
var maskSpecial = '!"$%^&*(){}[];#,./:@~<>?|_+-=';
var maskRandomNo = getRandomInt(0, 3);
var selectMask = [maskLcaseChar, maskUcaseChar, maskNumeric, maskSpecial];
return selectMask[maskRandomNo];
}
function passwordChecker(output, minSize){
var checkChars = '!"$%^&*(){}[];#,./:@~<>?|_+-=';
if (output.length < minSize){
return false
}
else if((output.toUpperCase() != output) && (output.toLowerCase() != output)) {
for (var i = 0; i < output.length; i++) {
if (checkChars.indexOf(output.charAt(i)) != -1) {
return true;
}
}
}
return false;
}
1 ответ
Таким образом, проблема, похоже, связана с функцией getRandomInt, которая возвращает int между 0 и длиной маски. Поскольку вы имеете дело с массивами, вы действительно хотите, чтобы он был между 0 и длиной массива -1.
Вы возвращали пустые строки из функции charAt, когда просили позицию вне массива.
Я исправил это, а также немного оптимизировал секцию генерации. Он всегда добавляет по одному символу от каждой из масок, а затем выбирает их случайным образом. Затем я тасую строку, перемещая начальные 4 вокруг. Он не использует крипто, чтобы перетасовать, но я не думаю, что это необходимо там.
function cryptoPassword(){
var maskLcaseChar = 'abcdefghijklmnopqrstuvwxyz';
var maskUcaseChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var maskNumeric = '0123456789';
var maskSpecial = '!"$%^&*(){}[];#,./:@~<>?|_+-=';
var maskAll = maskLcaseChar + maskUcaseChar + maskNumeric + maskSpecial;
var mask = '';
var minFieldNum = 8; //Minimum char size of desired output
var maxFieldNum = 40; //X defines their fields as 40 as the max_length
var outputValue = ''; //Output for field/overall function
var fieldRandom = getRandomInt(minFieldNum, maxFieldNum); //Generate length of password
if (fieldRandom < minFieldNum || fieldRandom > maxFieldNum) {
console.log("error length", fieldRandom)
fieldRandom = getRandomInt(minFieldNum, maxFieldNum); //Regenerate if length doesn't conform - Not working?
}
else {
var randomChar = '';
var rnd;
randomChar = maskLcaseChar.charAt(getRandomInt(0,maskLcaseChar.length)); //Pick random lower case
outputValue += randomChar; //Add to output
randomChar = maskUcaseChar.charAt(getRandomInt(0,maskUcaseChar.length)); //Pick random upper case
outputValue += randomChar; //Add to output
randomChar = maskNumeric.charAt(getRandomInt(0,maskNumeric.length)); //Pick random numeric
outputValue += randomChar; //Add to output
randomChar = maskSpecial.charAt(getRandomInt(0,maskSpecial.length)); //Pick random special
outputValue += randomChar; //Add to output
mask = maskAll;
for (var i = 3; i < fieldRandom; i++) {
randomChar = mask.charAt(getRandomInt(0,mask.length)); //Pick random char
outputValue += randomChar;
}
outputValue = shuffleString(outputValue); //shuffle output
if (passwordChecker(outputValue, minFieldNum)) {
return outputValue + passwordChecker(outputValue, minFieldNum);
}
else {
console.log("error password", outputValue);
}
}
}
function shuffleString(inputString) {
var array = inputString.split('');
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array.join('');
}
function getRandomInt(min, max) {
var byteArray = new Uint8Array(1);
window.crypto.getRandomValues(byteArray);
var range = (max - min);
var output = min + (byteArray[0] % range);
return output
}
function passwordChecker(output, minSize){
var checkChars = '!"$%^&*(){}[];#,./:@~<>?|_+-=';
if (output.length < minSize){
console.log("too short")
return false
}
else if((output.toUpperCase() != output) && (output.toLowerCase() != output)) {
for (var i = 0; i < output.length; i++) {
if (checkChars.indexOf(output.charAt(i)) != -1) {
if(output.indexOf(' ') === -1){
return true;
}
}
}
}
console.log("doesn't meet standards")
return false;
}
for(j=0; j<10000; j++){
cryptoPassword()
}
console.log("done")
Я добавил быстрый тест внизу. Он сгенерирует 10000 паролей. Он выведет их на консоль, только если они не пройдут ваш тест. Вы, вероятно, захотите удалить это и некоторые из console.logs и немного привести в порядок.