This is a short tutorial to get you started with Password Rodeo.

Introduction

The two main classes in Password Rodeo are PasswordMaker and PasswordChecker.

The first one allows you to generate random passwords according to a set of criteria you specify. The second one allows you to validate passwords submitted by your users, again according to a set of criteria that you get to specify.

We’ll examine first how to check passwords submitted by the users of your application and then how to generate random passwords.

Validating Passwords with PasswordChecker

Let’s assume we need the users of our application to create a password before they can log in. Let’s also assume that we would like this password to be minimally secure, and therefore we’ll require their password to be at least 8 characters long and contain at least one lower-case letter, one upper-case letter and one digit.

Let’s create a PasswordChecker to do just that:

var checker = PasswordChecker.factory()
        .setMinMaxLength(8, 16)
        .addCharGroup(CharacterGroups.LOWER_CASE, 1)
        .addCharGroup(CharacterGroups.UPPER_CASE, 1)
        .addCharGroup(CharacterGroups.DIGITS, 1)
        .create();
The second argument of setMinMaxCharCount specifies the maximum length of the password. This argument is mandatory and should be set to a value between 2 and 5 times the minimum length. (Unlimited password lengths can lead to security issues. Feel free to research the subject on the internet.)
The first argument to addCharGroup is a String that contains characters allowed in the password (for exemple "abcdefgh"). The CharacterGroups class contains a few pre-defined character lists to get you started.

To check if a password matches the validation criteria, you can use one of three functions provided by PasswordChecker: quickCheck, check or fullCheck.

If you need a simple yes or no answer, use quickCheck:

assert checker.quickCheck("Abcdef12") == true;
assert checker.quickCheck("Abcdef1") == false;   // too short
assert checker.quickCheck("Abcdefgh") == false;  // no digit
assert checker.quickCheck("@bcdef12") == false;  // illegal character

If you need to know why a password is rejected, use the check function:

assert checker.check("Abcdef12").equals(PasswordCheckStatus.OK);
assert checker.check("Abcdef1").equals(PasswordCheckStatus.TOO_SHORT);
assert checker.check("Abcdefgh").equals(PasswordCheckStatus.NOT_ENOUGH_OF_CHARACTER_GROUP); // no digit
assert checker.check("@bcdef12").equals(PasswordCheckStatus.ILLEGAL_CHARACTER);

The check function return a value from the enum PasswordCheckStatus that either indicates that the password is OK, or the first error condition encountered that you can then report to the user.

As mentioned only the first error detected is returned by this method. If you need a full report, you need to use the fullCheck method. This method returns a List of PasswordCheckErrors. The List is empty if there is no error, otherwise it’s possible to iterate over the List to process each error.

If the error is of type ILLEGAL_CHARACTER, the PasswordCheckError in the list is actually a subclass, IllegalCharacterError, on which the method getIllegalCharacter can be called to identify the illegal character.

If the error is of type NOT_ENOUGH_OF_CHARACTER_TYPE or TOO_MANY_OF_CHARACTER_TYPE, the PasswordCheckError in the list will be of the BadCountForCharacterTypeError subclass, which contains methods to identify the character list concerned and further details regarding the bad character counts.

Here is an exemple:

List<PasswordCheckError> errors = checker.fullCheck("Ab$@");
PasswordCheckError tooShort = errors.get(0);
assert tooShort.getErrorType().equals(PasswordCheckStatus.TOO_SHORT);

assert errors.get(1).getErrorType().equals(PasswordCheckStatus.ILLEGAL_CHARACTER);
IllegalCharacterError illegalChar1 = (IllegalCharacterError) errors.get(1);
assert illegalChar1.getIllegalCharacter().equals("$");

assert errors.get(2).getErrorType().equals(PasswordCheckStatus.ILLEGAL_CHARACTER);
IllegalCharacterError illegalChar2 = (IllegalCharacterError) errors.get(2);
assert illegalChar2.getIllegalCharacter().equals("@");

assert errors.get(3).getErrorType().equals(PasswordCheckStatus.NOT_ENOUGH_OF_CHARACTER_GROUP);
BadCountForCharacterTypeError missingCharType = (BadCountForCharacterTypeError) errors.get(3);
assert missingCharType.getCharacterGroup().equals(CharacterGroups.DIGITS);
assert missingCharType.getExpectedCount() == 1;
assert missingCharType.getActualCount() == 0;

As you can see there are 4 problems with this password that all get reported in detail:

  • the password is too short (error 0);

  • the character $ is not allowed (error 1);

  • the character @ is not allowed (error 2);

  • the password doesn’t contain any digit (error 3).

For a more thorough presentation of password validation, and the fullCheck method in particular, please refer to the full Manual.

Two more configuration examples

Before tackling password generation, let’s look at two more examples.

Let’s assume, we would like to impose more stringent constraints on user passwords and decide that our passwords should have a minimum length of 16 characters and a maximum length of 64 characters. Furthermore, we want the passwords to be composed of a mix of upper-case and lower-case letters and digits with at least one of each type of characters present. We would also like to allow the user to use symbols in their password (like $, &, *, etc.)

Here is how to do it:

var checker = PasswordChecker.factory()
        .setMinMaxLength(16, 64)
        .addCharGroup(CharacterGroups.LOWER_CASE, 1)
        .addCharGroup(CharacterGroups.UPPER_CASE, 1)
        .addCharGroup(CharacterGroups.DIGITS, 1)
        .addCharGroup(CharacterGroups.SYMBOLS)
        .create();
The PasswordChecker class uses an internal factory class to initialize its instances.

Here is a more extreme example: the password needs to be at least 32 characters long and no more than 160; it has to be composed of upper and lower-case characters, digits and symbols. At least one of each type of characters must be present. Also, we don’t want more than 5 digits or 3 symbols.

Here is the code to implement this:

var checker = PasswordChecker.factory()
        .setMinMaxLength(32, 160)
        .addCharGroup(CharacterGroups.LOWER_CASE, 1)
        .addCharGroup(CharacterGroups.UPPER_CASE, 1)
        .addCharGroup(CharacterGroups.DIGITS, 1, 5)
        .addCharGroup(CharacterGroups.SYMBOLS, 1, 3)
        .create();
This is just a weird example. Please be reasonable with the constraints you place on your users' passwords.

Creating Passwords with PasswordMaker

Let’s go back to our first example of a minimally secure password, containing between 8 and 16 characters, with upper-case and lower-case characters and digits (with at least one character in each of these categories).

To generate these kinds of passwords, you would use:

var maker = PasswordMaker.factory()
        .setLength(12)
        .addCharGroup(CharacterGroups.LOWER_CASE, 1)
        .addCharGroup(CharacterGroups.UPPER_CASE, 1)
        .addCharGroup(CharacterGroups.DIGITS, 1)
        .create();

You can then call maker.create() to generate 12 characters long passwords that comply with the criteria specified above.

Let’s build something a little more secure:

  • 32 characters long;

  • at least one upper-case and one lower-case character;

  • between 1 and 3 digits;

  • 2 symbols;

  • and also we want to avoid similar characters that could confuse the user (like 1 vs. I vs. l, or 0 vs. o vs. O).

var maker = PasswordMaker.factory()
        .setLength(12)
        .addCharGroup(CharacterGroups.UNAMBIGUOUS_LOWER_CASE, 1)
        .addCharGroup(CharacterGroups.UNAMBIGUOUS_UPPER_CASE, 1)
        .addCharGroup(CharacterGroups.UNAMBIGUOUS_DIGITS, 1, 3)
        .addCharGroup(CharacterGroups.UNAMBIGUOUS_SYMBOLS, 2, 2)
        .create();
CharacterGroups contains list of unambiguous characters you can use to help your users. It’s best to avoid these characters if your users will need to type their password in, especially on a mobile device.

Another example: let’s say we need to generate a random 20 hexadecimal digits string:

var maker = PasswordMaker.factory()
        .setLength(20)
        .addCharGroup("0123456789ABCDEF")
        .create();

What if you need a random string of characters and numbers to be part of a user-specific URL (password reset link for example). How about:

var maker = PasswordMaker.factory()
        .setLength(64)
        .addCharGroup(CharacterGroups.LOWER_CASE)
        .addCharGroup(CharacterGroups.UPPER_CASE)
        .addCharGroup(CharacterGroups.DIGITS)
        .create();
You can use PasswordMaker in many situations that requires the creation of a random string of characters according to a predefined pattern.
Internally PasswordMaker uses ThreadLocalRandom.current() to generate random numbers for password creation. You can specify your own source of random numbers if you need to. Please refer to the full Manual for this.

Conclusion

I hope that this short tutorial gave you all the information needed to get started with Password Rodeo. For more information, please refer to the Password Rodeo Manual or the Javadoc.