在java

时间:2015-11-04 02:08:06

标签: java algorithm random passwords

我想创建一个密码生成器,根据用户设置的限制创建密码。限制是:

  1. 最小密码长度
  2. 最大密码长度
  3. 最低字母和数字
  4. 最低信件
  5. 最小大写字母
  6. 最小小写字母
  7. 最小数字
  8. 最大重复字符
  9. 我通过谷歌了解,大部分示例代码都不符合我的要求。所以我即兴发布了这样的代码:

    private char[] GeneratePassword(int minLength, int maxLength,
            int maxRepeatCharacter, int minLetterAndDigit, int minLetter,
            int minLowerCaseLetter, int minUpperCaseLetter, int minDigit) {
    
        final String LETTER = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
        final String DIGIT = "0123456789";
        final String[] randomSelector = {LETTER,UPPERCASE,LOWERCASE,DIGIT};
    
        int len = getRandomNumber(minLength, maxLength);
        char[] passwordGenerated = new char[len];
        char[] characterUsed = new char[len];
        int selection;
        int letterAndDigitUsed = 0;
        int letterUsed = 0;
        int lowerCaseLetterUsed = 0;
        int upperCaseLetterUsed = 0;
        int digitUsed = 0;
        int index = 0;
    
        if (minLength > maxLength) {
          // throw new IllegalArgumentException("Min.Length > Max.Length!");
        }
    
        if (minLetter + minDigit > minLetterAndDigit) {
          // throw new IllegalArgumentException("Error!");
        }
    
        while (index != len) {
            selection = getRandomNumber(0, randomSelector.length);
            if (selection == 0) {
                passwordGenerated[index] = LETTER.charAt(RandomUtils.nextInt(0,
                        LETTER.length()));
                if (checkRepeatCharacter(passwordGenerated[index],
                        characterUsed, index, maxRepeatCharacter) == false) {
                    characterUsed[index] = passwordGenerated[index];
                    index++;
                    letterUsed++;
                    letterAndDigitUsed++;
                    break;
                }
            } else if (selection == 1) {
                passwordGenerated[index] = UPPERCASE.charAt(RandomUtils
                        .nextInt(0, UPPERCASE.length()));
                if (checkRepeatCharacter(passwordGenerated[index],
                        characterUsed, index, maxRepeatCharacter) == false) {
                    characterUsed[index] = passwordGenerated[index];
                    index++;
                    upperCaseLetterUsed++;
                    letterAndDigitUsed++;
                    break;
                }
            } else if (selection == 2) {
                passwordGenerated[index] = LOWERCASE.charAt(RandomUtils
                        .nextInt(0, LOWERCASE.length()));
                if (checkRepeatCharacter(passwordGenerated[index],
                        characterUsed, index, maxRepeatCharacter) == false) {
                    characterUsed[index] = passwordGenerated[index];
                    index++;
                    lowerCaseLetterUsed++;
                    letterAndDigitUsed++;
                    break;
                }
            } else if (selection == 3) {
                passwordGenerated[index] = DIGIT.charAt(RandomUtils.nextInt(0,
                        DIGIT.length()));
                if (checkRepeatCharacter(passwordGenerated[index],
                        characterUsed, index, maxRepeatCharacter) == false) {
                    characterUsed[index] = passwordGenerated[index];
                    index++;
                    digitUsed++;
                    letterAndDigitUsed++;
                    break;
                }
            }
        }
    
        return passwordGenerated;
    }
    
    private boolean checkRepeatCharacter(char passwordGenerated,
            char[] passwordUsed, int index, int maxRepeatCharacter) {
        int characterRepeated = 0;
        for (int i = 0; i < index; i++) {
            if (String.valueOf(passwordUsed[i]).equals(
                    String.valueOf(passwordGenerated))) {
                characterRepeated++;
                if (characterRepeated == maxRepeatCharacter) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private int getRandomNumber(int minLength, int maxLength) {
        Random r = new Random();
        return r.nextInt(maxLength - minLength) + minLength;
    }
    

    我遇到的问题是如何确保达到最低条件。与此同时,我不希望通过重复使用相同类型的角色来生成密码。

    1. 示例:如果我将最大密码长度设置为10,并且我希望最小数字为5.我更喜欢1jP2k3o4m9而不是57812aJ9tP

    2. 第二个示例:如果我将最大密码长度设置为5,并且我希望最小小写字母为3.我更喜欢Pj9mn而不是jkl5V

      < / LI>

      如您所见,第二个生成的密码首先尝试满足最低要求,然后只对其他字符类型进行随机选择。这将使密码更容易受到攻击。有没有办法做这个算法。

      参考:Generating a Random Password with Restrictions in Java

2 个答案:

答案 0 :(得分:2)

我会看一下像vt-password这样的东西:

https://code.google.com/p/vt-middleware/wiki/vtpassword

除了根据一些相当标准的必需特性提供灵活的密码验证机制外,它还支持生成符合“字符规则”列表所定义条件的密码:

https://code.google.com/p/vt-middleware/wiki/vtpassword#Generating_passwords

值得注意的是,该项目已经从孵化中毕业,现在被称为Passay - http://www.passay.org/

当前password generator JavaDocs不反映vt-password可用的同一组字符规则。您可以使用vt-password运行一段时间,也可以提供自己的$request='{ "weight": 0, "precondition": "{\"_deviceId._SerialNumber\":\"C8Bjkjkjj5E372\"}", "configurations": [ { "type": "value", "name": "InternetGatewayDevice.Time.NTPServer1", "value": "ntp1.sssdssd.com" }, { "type": "value", "name": "InternetGatewayDevice.Time.NTPServer3", "value": "ntp.dfdfkdshfksfd.org" } ] }'; $location='http://localhost:7557/presets/inform'; $response=curlRequest($request,$location); function curlRequest($request, $location) { $ch = curl_init($location); $curlOptions = array( CURLOPT_URL => $location, // CURLOPT_RETURNTRANSFER => true, // CURLOPT_FOLLOWLOCATION => true, // CURLOPT_MAXREDIRS => 10, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $request, CURLOPT_PROXY => 'proxy.example.com', CURLOPT_PROXYPORT => 8080 , CURLOPT_TIMEOUT => SOAP_CONN_TIMEOUT, CURLOPT_SSLVERSION => 3, CURLOPT_SSL_VERIFYPEER => false, ); // curl_setopt_array($ch, $curlOptions); $response = curl_exec($ch) or die (curl_error($ch)); return $response; } 实现来使用Passay生成器(+验证器,如果也需要)。

答案 1 :(得分:1)

我修复了我的代码。到目前为止,我已经测试过,我按要求完美运行。我留下这段代码以防万一其他人将来需要它。

private boolean checkRepeatCharacter(char randomCharacter,
        ArrayList<Character> passwordUsed, int usedLength,
        int maxRepeatCharacter) {
    int characterRepeated = 0;
    for (int i = 0; i < usedLength; i++) {
        if (String.valueOf(passwordUsed.get(i)).equals(
                String.valueOf(randomCharacter))) {
            characterRepeated++;
            if (characterRepeated == maxRepeatCharacter) {
                return false;
            }
        }
    }
    return true;
}

private boolean checkUsedIndex(int index, ArrayList<Integer> usedIndex) {
    for (int i = 0; i < usedIndex.size(); i++) {
        if (usedIndex.contains(index)) {
            return false;
        }
    }
    return true;
}

private int getRandomNumber(int minLength, int maxLength) {
    Random r = new Random();
    return r.nextInt(maxLength - minLength) + minLength;
}

public String generatePassword(int minLength, int maxLength,
        int maxRepeatCharacter, int minLetterAndDigit, int minLetter,
        int minLowerCaseLetter, int minUpperCaseLetter, int minDigit,
        int minSpecialCharacter, String specialCharacter) {

    final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
    final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    final String DIGIT = "0123456789";
    StringBuilder ALL = new StringBuilder();
    ALL.append(LOWERCASE);
    ALL.append(UPPERCASE);
    ALL.append(DIGIT);
    ALL.append(specialCharacter);
    ALL.toString();

    char getRandom;
    int length = 0;
    StringBuilder passwordGenerated = new StringBuilder();
    ArrayList<Character> characterUsed = new ArrayList<Character>();
    ArrayList<Integer> indexUsed = new ArrayList<Integer>();

    int passwordLength = 0;
    int lowerCaseLetterUsed = 0;
    int upperCaseLetterUsed = 0;
    int letterUsed = 0;
    int digitUsed = 0;
    int letterAndDigitUsed = 0;
    int specialCharacterUsed = 0;

    if (minLength > maxLength) {
        throw new IllegalArgumentException("Min. Length > Max. Length!");
    }

    if (minUpperCaseLetter + minLowerCaseLetter > minLetter) {
        throw new RuntimeException(
                "mininimum Lower Case + Minimum Uppercase cannot exceed minLetter");
    }
    if (minLetter + minDigit > minLetterAndDigit) {
        throw new RuntimeException(
                "mininimum Letter + Minimum Digit cannot exceed minimum Letter And Digit");
    }
    if (minLetter + minDigit + minSpecialCharacter > maxLength) {
        throw new RuntimeException(
                "minimum Digit + minimum Letter + Minimum Special Character cannot excced maximum Length");
    }

    while ((length < minLetter) && (length < minLetterAndDigit)) {
        length = getRandomNumber(minLength, maxLength);
    }

    while (passwordLength != length) {
        while (letterAndDigitUsed < minLetterAndDigit) {
            while (letterUsed < minLetter) {
                lowerCaseLetterUsed = 0;
                for (int i = 0; lowerCaseLetterUsed < minLowerCaseLetter; i++) {
                    int index = getRandomNumber(0, length);
                    if (checkUsedIndex(index, indexUsed) == true) {
                        getRandom = LOWERCASE.charAt(getRandomNumber(0,
                                LOWERCASE.length()));
                        if (checkRepeatCharacter(getRandom, characterUsed,
                                characterUsed.size(), maxRepeatCharacter) == true) {
                            passwordGenerated.append(getRandom);
                            characterUsed.add(getRandom);
                            indexUsed.add(index);
                            lowerCaseLetterUsed++;
                            letterUsed++;
                            letterAndDigitUsed++;
                            passwordLength++;
                            if (letterUsed == minLetter) {
                                break;
                            }
                        }
                    }
                }
                if (letterAndDigitUsed == minLetterAndDigit) {
                    break;
                }
                upperCaseLetterUsed = 0;
                for (int i = 0; upperCaseLetterUsed < minUpperCaseLetter; i++) {
                    int index = getRandomNumber(0, length);
                    if (checkUsedIndex(index, indexUsed) == true) {
                        getRandom = UPPERCASE.charAt(getRandomNumber(0,
                                UPPERCASE.length()));
                        if (checkRepeatCharacter(getRandom, characterUsed,
                                characterUsed.size(), maxRepeatCharacter) == true) {
                            passwordGenerated.append(getRandom);
                            characterUsed.add(getRandom);
                            indexUsed.add(index);
                            lowerCaseLetterUsed++;
                            letterUsed++;
                            letterAndDigitUsed++;
                            passwordLength++;
                            if (letterUsed == minLetter) {
                                break;
                            }
                        }
                    }
                }
                if (letterAndDigitUsed == minLetterAndDigit) {
                    break;
                }
            }
            for (int i = 0; digitUsed < minDigit; i++) {
                int index = getRandomNumber(0, length);
                if (checkUsedIndex(index, indexUsed) == true) {
                    getRandom = DIGIT.charAt(getRandomNumber(0,
                            DIGIT.length()));
                    if (checkRepeatCharacter(getRandom, characterUsed,
                            characterUsed.size(), maxRepeatCharacter) == true) {
                        passwordGenerated.append(getRandom);
                        characterUsed.add(getRandom);
                        indexUsed.add(index);
                        digitUsed++;
                        letterAndDigitUsed++;
                        passwordLength++;
                    }
                }
            }
        }
        for (int i = 0; specialCharacterUsed < minSpecialCharacter; i++) {
            if (checkUsedIndex(i, indexUsed) == true) {
                getRandom = specialCharacter.charAt(getRandomNumber(0,
                        specialCharacter.length()));
                if (checkRepeatCharacter(getRandom, characterUsed,
                        characterUsed.size(), maxRepeatCharacter) == true) {
                    passwordGenerated.append(getRandom);
                    characterUsed.add(getRandom);
                    indexUsed.add(i);
                    specialCharacterUsed++;
                    passwordLength++;
                }
            }
        }
        for (int i = 0; i < length; i++) {
            if (checkUsedIndex(i, indexUsed) == true) {
                getRandom = ALL.charAt(getRandomNumber(0, ALL.length()));
                if (checkRepeatCharacter(getRandom, characterUsed,
                        characterUsed.size(), maxRepeatCharacter) == true) {
                    passwordGenerated.append(getRandom);
                    characterUsed.add(getRandom);
                    indexUsed.add(i);
                    passwordLength++;
                }
            }
        }
    }
    return passwordGenerated.toString();
}