1

我正在尝试构建一个密码生成器,它创建的密码符合:

  1. 最少 8 个字符,最多 40 个字符
  2. 必须包含至少 1 个大写、小写、数字和符号

我避免选择 Math.random,我更喜欢加密选项。

我已经阅读了大量文章来尝试使其正常工作,但我遇到了以下问题:

  1. 随机空格似乎出现在输出字符串中,通常出现在末尾。

  2. 输出值有时不符合 min 8 char 规则。

我意识到我可能有太多额外的 if 语句仔细检查了事情,但我很难看出哪里出了问题。

这是为了进入另一个系统,所以我将它创建为尽可能模块化和功能性。为下面的大片段道歉,我无法让它工作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;
}
4

1 回答 1

0

所以问题似乎出在 getRandomInt 函数上,它会返回一个介于 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")

我在底部添加了一个快速测试。它将生成 10,000 个密码。如果测试失败,它只会将它们输出到控制台。您可能想要删除它和一些 console.logs 并稍微整理一下。

于 2016-04-22T10:34:22.130 回答