How do I create a random password that meets the system's length and character set requirements in Java?
I have to create a random password that is 10-14 characters long and has at least one uppercase, one lowercase, and one special character. Unfortunately, some special characters are too special and cannot be used, so I cannot use just printed ASCII.
Many of the examples on this site generate a random password or session key without enough entropy in the characters or without realistic requirements in a business setting like the ones given above, so I'm asking more pointed question to get a better answer.
My character set, every special character on a standard US keyboard except for a space:
A-Z
a-z
0-9
~`!@#$%^&*()-_=+[{]}\|;:'",<.>/?
Here is a utility that uses just vanilla Java and implements the requirements. It basically gets one of each of the required character sets. Then populates the rest with random chars from the whole set. Then shuffles it all up.
Using the random functionality of java.util package of rt.jar, we can create a random password of any length. below is the snippet for the same.
}
I suggest using apache commons RandomStringUtils. Use something what is already done.
If you are using maven
otherwise download jar
UPDATE Version with secure random. So matter of required characters left and can be solved as in comment, generate required parts separately and normal ones. Then join them randomly.
I recently learned about Passay. It provides the required functionality needed in its PasswordGenerator class. It randomly generates passwords meeting the requirements similar to what is written below using CharacterRules rather than PasswordCharacterSets as I have done below. Instead of holding a list of unused indexes for random character insertion, it simply shuffles the character buffer after inserting characters that meet the requirements.
Below is left over from before, I recommend using Passay if your licensing allows it, this code should work otherwise and provides details of why the generated passwords are crytographically strong
I ended up writing this code twice. Once to get a random character result, but it turned out the distribution of characters depended on the size of the character set(whoops!). I rewrote it and now you should just copy/paste the code and change the Main.java to the character sets you want. Although it could have been done differently, I think this is a relatively straightforward approach to get the correct result and I encourage reuse, comments, criticisms, and well-thought edits.
The controls of the PasswordGenerator code is as follows:
The main bits for the actual password generation:
Description of password complexity: Password complexity is usually talked about in bits of entropy. Here are the number of possibilities for your keyspace:
There is at least one uppercase alpha character (out of 26), one lowercase alpha character(out of 26), one digit (out of 10), and one special character (out of 32), the way you calculate the number of possibilities is the number of possibilities for each character multiplied by the number of characters since they are randomly placed in the string. So we know the possibilities for four of the characters are:
All remaining characters have 94 (26+26+10+32) possibilities each
Our calculation is:
With this is mind, if you want the most secure passwords, you should always choose the highest amount of characters possible which is 14 in this case.
Main.java
PasswordGenerator.java