-
Notifications
You must be signed in to change notification settings - Fork 65
Description
I have the following case: the password should contain at least 3 lowercase letters, 3 uppercase letters, 3 digits, and should not repeat the same character more than 3 times.
The PasswordGeneration process includes a retry mechanism to regenerate the password if any non-character rules are invalid.
However, we encounter a problem in this case.
public String generatePassword(final int length, final List<? extends Rule> rules)
{
if (length <= 0) {
throw new IllegalArgumentException("length must be greater than 0");
}
final StringBuilder allChars = new StringBuilder();
final CharBuffer buffer = CharBuffer.allocate(length);
final PasswordValidator validator = new PasswordValidator(rules);
if (rules != null) {
for (Rule rule : rules) {
if (rule instanceof CharacterRule) {
final CharacterRule characterRule = (CharacterRule) rule;
fillRandomCharacters(
characterRule.getValidCharacters(),
Math.min(length, characterRule.getNumberOfCharacters()),
buffer);
allChars.append(characterRule.getValidCharacters());
}
}
}
String generated;
int count = 0;
do {
fillRandomCharacters(allChars, length - buffer.position(), buffer);
// cast to Buffer prevents NoSuchMethodError when compiled on JDK9+ and run on JDK8
((Buffer) buffer).flip();
randomize(buffer);
generated = buffer.toString();
if (count > 0) {
retryCount++;
}
} while (count++ <= RETRY_LIMIT && !validator.validate(new PasswordData(generated)).isValid());
if (count > RETRY_LIMIT) {
throw new IllegalStateException("Exceeded maximum number of password generation retries");
}
return generated;
}If any of the non-character rules are invalid, the second while loop starts without going through the character rules loop, and the password is generated using only the available allChars. This process ignores the rules regarding the required number of characters.
The regenerated password from the second loop also becomes invalid due to the required number of character rule.
As a result, after 2 retries a generation error occurs.
It seems that during the password regeneration, all the characters rules should be considered as well.