Password-based authentication schemes do sometimes require that a password is generated automatically. An example of this is when users forget their password thus necessitating a programmatic reset. Equally, some users may simply not want to go through the bother of creating a password themselves and prefer that an application generates one for them.
The task that faces the application programmer in scenarios such as these is how to ensure that the generated password follows internally defined security standards. Given that in today's world, passwords must meet minimum strength requirements e.g. mix of upper and lower case, alpha numeric chars etc. Put differently, the application programmer must ensure that the generated password meets the strength requirements mandated by their organization, thus inevitably making their task simply more than one of generating any random sequence of characters.
The obix commons library not only implements a number of password rules, but also provides an easy and intuitive way to apply these to generate passwords reliably. The core classes and interface for this functionality live in the security package, and are PasswordGenerator and PasswordRequirement. As we will see in the coming sections, the PasswordRequirement encapsulates a password rule e.g. the minimum number of lowercase characters, whilst the PasswordGenerator is responsible for applying these rules in order to arrive at a password. Thus, when generating a password only one PasswordGenerator is required, but more than one PasswordRequirement will typically be required (at least for a strong password).
A number of examples are provided by the obix team to demonstrate password generation. These can be obtained from our subversion repository. Please note that you will need an obix labs account in order to access the repository.
To see how to generate a weak password, download the password-generator samples application from our subversion repository. Set-up the project in your favourite IDE and navigate to the class TextOnlyPasswordGeneratorDemo. If you execute this class, it will output a simple password which consists of a mixture of lower and upper-case characters.
Now, lets delve into the code, which is shown in the following excerpt.
int desiredPasswordLength = 8;
//create an array containing the simplest password requirement
ArrayList<PasswordRequirement> requirements =
new ArrayList<PasswordRequirement>();
requirements.add(new SimpleAlphaCharsFillPasswordRequirement(desiredPasswordLength));
//create the generator
PasswordGenerator generator = new PasswordGeneratorDefaultImpl();
//then generate the password
String password = generator.generatePassword(requirements);
System.out.println("Simple password is:\n" + password);
In the first three statements of this code we are creating a list consisting of a single password requirement or rule, the SimpleAlphaCharsFillPasswordRequirement. The use of a list here is mandatory as the generator requires a list of rules to which the generated password must conform. The SimpleAlphaCharsFillPasswordRequirement is a simple fill rule i.e. it fills the password with a pre-determined number of random lower and upper case characters. For this reason, and as you will see in further examples, it generally serves as the base rule for most password generation schemes.
Having defined our list of PasswordRequirements, we instantiate the PasswordGenerator implementation provided by the library, and invoke the generatePassword method. This applies the instantiated rules to a new PasswordBuffer and returns the resulting text.
In this section we will demonstrate how the commons library can be used to generate a strong password. We define a strong password as one which consists of at least one of each of the following: a number; an upper-case letter; a lower-case letter; and a non-alpa-numeric character. The sample class demonstrating how to generate a strong password is included in the sample application described in the previous section, and which can be downloaded from our subversion repository. The class of interest in the application is the StrongPasswordGeneratorDemo. To see its output, simply execute the main method via your favourite IDE. On doing so, you will notice that the password it prints out is consistent with the above definition of a strong password. To understand how it works, we will need to delve further into the code. Let us begin with the main method, portions of which is excerpted below.
int minimumPasswordLength = 8;
//create an array containing the simplest password requirement
List<PasswordRequirement> requirements = buildRequirements(minimumPasswordLength);
//create the generator
PasswordGenerator generator = new PasswordGeneratorDefaultImpl();
//then generate the password
String password = generator.generatePassword(requirements);
As you will notice, its structure is not altogether dissimilar to the structure of the main method from the previous example on simple password generation. We still specify a minimum requirement for the password, and we still pass a list of PasswordRequirements to the PasswordGenerator. What does differ is that we now use a convenience method to build our list of PasswordRequirements. Our readers can feel free to make a Sherlock Holmes style deduction that the difference in logic between both examples must lie in the body of this method, relevant sections which are excerpted below, and which we will now examine.
ArrayList<PasswordRequirement> result =
new ArrayList<PasswordRequirement>();
//add a simple fill requirement to give us an initial weak password
result.add(new SimpleAlphaCharsFillPasswordRequirement(minimumPasswordLength));
//add some strenghtening rules
//at least one lowercase character
result.add(new MinLowerCaseCharsPasswordRequirement());
//at least one uppercase character
result.add(new MinUpperCaseCharsPasswordRequirement());
//at least one number
result.add(new MinNumericCharsPasswordRequirement());
//at least one punctuation character
result.add(new MinNonAlpaNumericCharsPasswordRequirement());
return result;
Notice that the first rule we add is the SimpleAlphaCharsFillPasswordRequirement from the previous example. We do this so that the PasswordGenerator starts with an initial password of a minimum size regardless of the strength of the password. After this rule, we then add a number of hardening rules, specifcally the MinLowerCaseCharsPasswordRequirement, MinUpperCaseCharsPasswordRequirement, MinNumericCharsPasswordRequirement and MinNonAlpaNumericCharsPasswordRequirement rules, which mirror our definition of a strong password. These will correct any weaknesses in the original password with which the PasswordGenerator begins.
So the next question is whether or not the order of the rules is important? The simple answer is no, but it is recommended that your requirements list starts with a SimpleAlphaCharsFillPasswordRequirement. To see why, you should try changing the order of the rules in the sample application. As a simple exercise, you could try reversing the order of the rules and placing the first last. If you re-run the application, do you notice any differences in the output? And if you run it a few times?
You will probably notice that the output is less random than with the original ordering, which will probably not be acceptable to a large number of people; from our experience, predictability is not normally a requirement for a password generator. The reason why the reverse ordering is not so random is that when the hardening rules are applied to a non-empty buffer, they will pick random indices within the buffer to harden. Whilst if applied to an empty buffer, they will simply insert elements into the buffer sequentially. This has the unwelcome side effect of all the characters which fulfil the password-rules clustering at the beginning of the password. Put differently, it is advisable to use the SimpleAlphaCharsFillPasswordRequirement rule as the initial password rule. This will produce an initial password of the minimum desired length. The hardening rules can then be subsequently applied, with the the effect that they can randomly replace elements in the password so as to make it harder.
What happens if you include multiple instances of the same password requirement in the requirements list? Does it affect the outcome of the generator?
Assume that you have been told by your internal security group that your password must contain at least 2 numbers instead of just one. How would you modify the above code to handle that.
Hint: Examine the constructor options for MinNumericCharsPasswordRequirement. For a detailed example, see the example class ExtraStrongPasswordGeneratorDemo from the sample application.
In some cases it may be useful to set a maximum bound for the password generator. This can be achieved via the overriden generate method implementation. The flip side of course is that if your password reaches this limit, and the password rules you have specified require more space, the generator will fail.