How do you generate a secure random (or pseudo-random) alphanumeric string in Java efficiently?
-
2hmm could you define what you mean by secure and random? is psuedo-random good enough for example? Or do you need cryptographic strength true randomness? – mikera Aug 18 '11 at 17:39
-
possible duplicate of [How to generate a random alpha-numeric string in Java](http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string-in-java) – erickson Aug 18 '11 at 17:42
-
pseudo-random would be good enough. – devon Aug 18 '11 at 19:16
-
3this is not a duplicate because the other question is not for a secure string. The one answer that is secure is not fast enough. – devon Aug 18 '11 at 19:18
-
Do you need to restrict the string to uppercase or lowercase only? Do you accept dashes? Do you have a specific length requirement, can any fixed length suffice, or will they have to be of random length also? Finally, define how fast is 'fast'? The basic `Random` or `SecureRandom` solution will both require *n* calls to `nextInt()`. – Alistair A. Israel Aug 19 '11 at 00:16
11 Answers
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.

- 678,734
- 91
- 1,224
- 1,255
-
3+1 for a good way to restrict a generated string to a defined list of characters. – Jason Wheeler Aug 18 '11 at 17:49
-
If you use Apache Commons Lang, the easiest way is
RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());

- 856
- 1
- 8
- 13
-
1This approach is not quite secure and leads to high predictability after several tries. I would go with SecureRandom or RandomStringGenerator.Builder. – ninjaxelite Dec 06 '21 at 13:55
-
5@ninjaxelite why? he is using SecureRandom as seed, the randomness comes from the new SecureRandom(), look here: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/RandomStringUtils.html – Roie Beck Dec 29 '21 at 19:41
-
1It is clearly specified as a **non secure**: Caveat: Instances of Random, upon which the implementation of this class relies, are not cryptographically secure. – Mikhail Ionkin Apr 08 '22 at 18:07
-
3The quoted comment is referring to the default source of randomness used by RandomStringUtils, which is `Random`. The answer is providing a `SecureRandom` instance, via a method which is explicitly designed and intended to override the default instance – RvPr Oct 11 '22 at 15:57
final String chrs = "0123456789abcdefghijklmnopqrstuvwxyz-_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final SecureRandom secureRandom = SecureRandom.getInstanceStrong();
final String customTag = secureRandom
.ints(9, 0, chrs.length()) // 9 is the length of the string you want
.mapToObj(i -> chrs.charAt(i))
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
System.out.println(customTag);
Examples:
// q3HX6EctP
// WjRrMjQT4
// sX-Piq4DB

- 6,148
- 6
- 38
- 76

- 25,162
- 40
- 190
- 357
Here's a slightly modified version of my code from the duplicate question.
public final class RandomString
{
/* Assign a string that contains the set of characters you allow. */
private static final String symbols = "ABCDEFGJKLMNPRSTUVWXYZ0123456789";
private final Random random = new SecureRandom();
private final char[] buf;
public RandomString(int length)
{
if (length < 1)
throw new IllegalArgumentException("length < 1: " + length);
buf = new char[length];
}
public String nextString()
{
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols.charAt(random.nextInt(symbols.length()));
return new String(buf);
}
}
-
This is not fast enough--maybe because of the multiple calls to nextInt()? – devon Aug 18 '11 at 19:45
-
Secure is slow. Insecure is fast. If you want a secure random number then it will take a little time. – rossum Aug 18 '11 at 22:11
-
@devon - Initializing a `SecureRandom` instance is slow. In fact, if it's implemented correctly on your system, it can take quite a while to gather enough entropy for a seed. Make sure that you don't count that initialization time in your tests. Or, if you don't need cryptographic quality, use a different RNG. – erickson Aug 19 '11 at 19:34
-
@Erickson I know your comment is old, but when testing this, it was very fast. In eclipse, the second I click run, it printed out my string. Does that mean something is wrong? Or is this fast 2 years later? – Michael Scott Dec 25 '13 at 04:48
-
1@MichaelScott It depends on the underlying operating system, and the "entropy gathering device" setting in the Java security properties. On Linux, there are two devices provided by the operating system that Java can read to get random seeds for new `SecureRandom` instances. One of the devices only returns random bits (generated slowly by timing various system events), and if you consume a lot of entropy on the system, it will soon block, and take a while to create new instances. The other device uses pseudo-random bits and is non-blocking. With this one, you wouldn't see any delays. – erickson Dec 25 '13 at 09:39
-
@Erickson I need this SecureRandom for security purposes, not simulation. Is there a way I can verify that the SecureRandom I am using will be appropriate for security purposes? I do not want pseudo-random. – Michael Scott Dec 26 '13 at 06:42
-
@MichaelScott [This article](http://resources.infosecinstitute.com/random-number-generation-java/) has good info about the various configuration options. An application can request an RNG with a particular algorithm from a particular provider; in the case of the Sun provider on Linux, the behavior depends on some system-wide configuration that would be hard for the application to verify. If it doesn't make specific requests, the application will receive the default RNG, and it would be difficult for it to assess its security. – erickson Dec 26 '13 at 22:09
import java.security.SecureRandom;
import java.util.Random;
public class PasswordHelper {
public static String generatePassword (int length) {
//minimum length of 6
if (length < 6) {
length = 6;
}
final char[] allAllowed = "abcdefghijklmnopqrstuvwxyzABCDEFGJKLMNPRSTUVWXYZ0123456789".toCharArray();
//Use cryptographically secure random number generator
Random random = new SecureRandom();
StringBuilder password = new StringBuilder();
for (int i = 0; i < length; i++) {
password.append(allAllowed[random.nextInt(allAllowed.length)]);
}
return password.toString();
}
}

- 13,640
- 5
- 54
- 83
-
1Great for generating random nonce for CSP headers! Just base64 encode it when you're done :) – eliteproxy Jun 16 '21 at 22:37
-
`//minimum length of 6 \ if (length < 4) { ... }`: the condition does not match the comment. – BairDev Sep 30 '21 at 09:48
-
Using UUIDs:
UUID random = UUID.randomUUID();
System.out.println( random );

- 39,901
- 14
- 121
- 158
-
17UUIDs are random enough for accidental collisions. However, they are NOT useable for security, they fail against an attacker actively trying to guess values. – Tito May 22 '13 at 14:57
-
-
4Length is NOT the problem with UUIDs/GUIDs. A 128 bits generated using a "cryptographically strong RNG" is fine (e.g. SecureRandom). The problem is that "random" has to be cryptographically random. GUIDS can be generated with a variety of algorithms and are not guaranteed to be cryptographically secure. For example: http://stackoverflow.com/questions/3652944/how-securely-unguessable-are-guids – Tito Jan 17 '16 at 03:33
-
3Even the RFC that defines UUIDs says "Do not assume that UUIDs are hard to guess; they should not be used as security capabilities" http://tools.ietf.org/html/rfc4122 – Tito Jan 17 '16 at 03:37
-
4This is a fine answer. Java's UUID uses java.security.SecureRandom and java.security.provider.SecureRandom... the predictability of this has been greatly exaggerated here. Some JVM's impl's may not be as good as the Sun/Oracle OOTB one... – Rondo May 13 '16 at 00:06
-
2The documentation for [UUID.randomUUID()](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID()) specifies that it uses a cryptographically strong pseudo random number generator. – Macil Sep 19 '18 at 00:45
My spec for this randomly generated string was to produce a 35 character length encryption key (a-zA-Z2-7 characters only for first 25 chars). After every 5th character a -
used, and the last 5 characters were to be an integer between 10_000 and 19_999.
Here's the code for what I did (in Kotlin).
companion object {
/**
* Letters lower & upper case excluding:
*
* - l, o, B, O
*
* Numbers excluding:
*
* - 0, 1, 8, 9
* */
val acceptedChars: CharArray
get() = charArrayOf(
'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j',
'k', 'm', 'n', 'p', 'q',
'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'A',
'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L',
'M', 'N', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '2', '3',
'4', '5', '6', '7'
)
val acceptedInts: CharArray
get() = charArrayOf(
'0', '1', '2', '3', '4',
'5', '6', '7', '8', '9'
)
fun generate(): EncryptionKey {
val random = SecureRandom()
val stringBuilder = StringBuilder()
for (i in 0 until 35) {
when (i) {
5, 11, 17, 23, 29 -> {
stringBuilder.append("-")
}
30 -> {
stringBuilder.append("1")
}
31, 32, 33, 34 -> {
val index = random.nextInt(acceptedInts.size)
stringBuilder.append(acceptedInts[index])
}
else -> {
val index = random.nextInt(acceptedChars.size)
stringBuilder.append(acceptedChars[index])
}
}
}
return EncryptionKey(stringBuilder.toString())
}
}
results produced:
value: 'nK6UI-DWYvu-dbmhD-KPe5X-22dPT-10027', length: '35'
value: 'NIFvi-aX4GW-3xCYV-YSAVs-tASIK-15301', length: '35'
value: 'SpNkT-qxHR7-hSMkK-hVxpp-AqLFh-19409', length: '35'
value: 'bNvi2-svqX7-cfEw5-LNYDn-C2FtW-16197', length: '35'
value: 'hhjLX-KmRQU-KbHyU-CkNyD-5ASk6-14537', length: '35'
value: 'Xd2cj-braCm-FaE4E-Jvn2G-2Dv5J-12243', length: '35'
value: '7beFb-aeSe2-iHXZe-mTUHT-aEbry-17349', length: '35'
value: 'NExMa-xCAbU-VkpyS-xeEkj-QUayd-16311', length: '35'
value: '52HWN-EX7wV-csbhj-InhtU-gbV46-18606', length: '35'
value: 'n3RTZ-whpjQ-ZjW5n-tTyfR-eLDSF-14003', length: '35'
value: 'aJEks-ccKdU-KGJdh-Rz4ck-tR7Uq-12199', length: '35'
value: 'nMcUF-ctbcy-FEfq7-VJhRx-pCKej-16369', length: '35'

- 311
- 3
- 5
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.
-
Could you please edit your answer and add a code sample implementing your suggestion? – sanastasiadis Oct 01 '21 at 19:29
Generate a public key for an open-key encryption algorithm and convert the byte sequence to string via Base64 algorithm.

- 239,200
- 50
- 490
- 574
I'm not sure about efficienty (probably you can't create much more efficient variant), but this variant is simple and secure (while RandomStringUtils is not):
SecureRandom randomGenerator = new SecureRandom();
byte[] randomBytes = new byte[20];
randomGenerator.nextBytes(randomBytes);
String randomString = new BigInteger(1, randomBytes).toString(16);
It you want to a little more efficient variant, specify randomGenerator as class field or as a static field.
Taked from https://stackoverflow.com/a/44227131/5122436

- 568
- 4
- 20
http://download.oracle.com/javase/6/docs/api/java/security/SecureRandom.html
From the Javadoc:
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);

- 872
- 1
- 9
- 23