You can use org.apache.commons.lang.RandomStringUtils (http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/RandomStringUtils.html) to generate password using char array and java.security.SecureRandom:
public String generatePassword()
{
return RandomStringUtils.random(DEFAULT_PASSWORD_LENGTH, 0, VALID_PW_CHARS.length(), false,
false, VALID_PW_CHARS.toCharArray(), new SecureRandom());
}
In pom.xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
Answer from jgr on Stack OverflowYou can use org.apache.commons.lang.RandomStringUtils (http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/RandomStringUtils.html) to generate password using char array and java.security.SecureRandom:
public String generatePassword()
{
return RandomStringUtils.random(DEFAULT_PASSWORD_LENGTH, 0, VALID_PW_CHARS.length(), false,
false, VALID_PW_CHARS.toCharArray(), new SecureRandom());
}
In pom.xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
Use StringBuilder instead of concatenating strings over and over. Also you should look at using string.charAt(index) instead of using substring for single chars:
import java.util.*;
import java.security.SecureRandom;
public class PassGen{
private static final String VALID_PW_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+{}[]|:;<>?,./";
private static final int DEFAULT_PASSWORD_LENGTH = 12;
private static final Random RANDOM = new SecureRandom();
// main class
public static void main(String args[]) throws Exception {
// Set password length
int pwLength;
if (args.length < 1)
pwLength = DEFAULT_PASSWORD_LENGTH;
else
pwLength = Integer.parseInt(args[0]);
StringBuilder pw = new StringBuilder();
// generate password
for (int i=0; i<pwLength; i++) {
int index = RANDOM.nextInt(VALID_PW_CHARS.length());
pw.append(VALID_PW_CHARS.charAt(index)));
}
System.out.println("pw = " + pw.toString());
}
}
Also you are generating doubles and not restricting the index value. I did a mod of the length of the valid chars array to fix this problem.
Initialize an array containing all the accepted chars (CHARS_ARRAY), then instantiate a SecureRandom instance, and call nextInt(CHARS_ARRAY.length) repeatedly to get a random index in your char array. Append each char to a StringBuilder until you get the expected number of chars.
If you use Apache Commons Lang, the easiest way is
RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
There is no seed provided in the implementation I found, there is just a new Random(). But there is a method where you can supply your own source of randomness
random(int count, int start, int end,
boolean letters, boolean numbers,
char[] chars, java.util.Random random)
You shouldn't use a random generator to generate unique keys. Nothing guarantees uniqueness. Why don't you use a UUID generator instead, or a database sequence?
And why do you want your keys to be properly distributed? The only important thing for a primary key is its uniqueness. And the seed doesn't have any impact on the distribution, AFAIK.