Recommended Java password generator
This class generates a 20-character password and requires lowercase, uppercase, numeric, and symbol characters.
import java.security.SecureRandom;
public final class PasswordGenerator {
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
private static final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
private static final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String DIGITS = "0123456789";
private static final String SYMBOLS = "!@#$%^&*()-_=+";
private static final String ALPHABET =
LOWERCASE + UPPERCASE + DIGITS + SYMBOLS;
private PasswordGenerator() {}
public static String generate(int length) {
if (length < 4) {
throw new IllegalArgumentException("length must be at least 4");
}
while (true) {
StringBuilder password = new StringBuilder(length);
for (int index = 0; index < length; index++) {
int position = SECURE_RANDOM.nextInt(ALPHABET.length());
password.append(ALPHABET.charAt(position));
}
String value = password.toString();
if (containsAny(value, LOWERCASE)
&& containsAny(value, UPPERCASE)
&& containsAny(value, DIGITS)
&& containsAny(value, SYMBOLS)) {
return value;
}
}
}
private static boolean containsAny(String value, String group) {
return value.chars().anyMatch(character -> group.indexOf(character) >= 0);
}
public static void main(String[] args) {
System.out.println(generate(20));
}
}
Compile with javac PasswordGenerator.java, then run java PasswordGenerator. The default SecureRandom constructor selects the first available provider implementation and seeds itself from an appropriate entropy source.
Use SecureRandom, not Random
Oracle documents SecureRandom as a cryptographically strong random number generator. The java.util.Random class is deterministic and its documentation explicitly directs security-sensitive applications to SecureRandom.
Do not use Math.random(), Random, ThreadLocalRandom, a timestamp, or a fixed seed for credentials. Those APIs and patterns are useful for simulations and reproducible tests, not secrets.
How the Java code works
- The four constants define an explicit, reviewable password alphabet.
SecureRandom.nextInt(ALPHABET.length())selects the next position.- The loop selects every password character independently from the full alphabet.
- The group checks reject candidates that do not satisfy the stated policy.
Rejecting the whole candidate avoids fixed patterns such as always placing an uppercase letter first or a digit last. The minimum length guard reflects the four required groups; it does not imply that four characters are strong.
Change the allowed characters
Many systems reject spaces, quotes, backslashes, or a broad punctuation set. The example intentionally uses a conservative symbol constant that is easy to edit. Define the accepted characters before random selection instead of generating from a larger alphabet and deleting characters afterward.
For alphanumeric output, set ALPHABET to LOWERCASE + UPPERCASE + DIGITS and remove the symbol requirement from the validation condition. Increase the length when possible because the alphabet is smaller.
Generate multiple unique passwords
A LinkedHashSet preserves output order and rejects a duplicate if one ever occurs inside the requested batch.
import java.util.LinkedHashSet;
import java.util.Set;
Set<String> passwords = new LinkedHashSet<>();
while (passwords.size() < 10) {
passwords.add(PasswordGenerator.generate(24));
}
passwords.forEach(System.out::println);
Generate a URL-safe token
Passwords and application tokens are different jobs. For a reset link, session identifier, or invitation token, generate random bytes and encode them without Base64 padding:
import java.security.SecureRandom;
import java.util.Base64;
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
String token = Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(bytes);
System.out.println(token);
The 32-byte input contains 256 random bits. Use the random token generator when you want equivalent Base64URL or hexadecimal output without writing Java.
Should you use getInstanceStrong()?
SecureRandom.getInstanceStrong() selects from algorithms named in the runtime's securerandom.strongAlgorithms security property. That does not automatically make it the best choice for a routine password method: provider behavior can vary, and a strong implementation may block while gathering entropy. The default new SecureRandom() is a practical cryptographic generator for this general-purpose example.
Choose a named provider or strong algorithm only when your application's documented security requirements call for it, then test that exact runtime and deployment environment.
Common Java password-generator mistakes
- Using
Random: identical seeds and calls reproduce identical sequences. - Manually setting a seed: a timestamp, account ID, or other guessable value can undermine the generator.
- Using modulo arithmetic: mapping an arbitrary random integer with
% alphabet.length()can bias selections. Use the boundednextIntmethod. - Forcing fixed positions: predictable group placement reduces the number of possible formats.
- Logging results: secure randomness cannot protect a password exposed by logs or diagnostics.
- Storing plaintext passwords: applications that verify user passwords need an appropriate salted password-hashing system rather than reversible storage.
Test the generator
Test policy properties across many outputs. Do not assert one exact value because a secure generator is intentionally non-deterministic.
for (int sample = 0; sample < 1_000; sample++) {
String value = PasswordGenerator.generate(20);
if (value.length() != 20
|| !value.chars().anyMatch(Character::isLowerCase)
|| !value.chars().anyMatch(Character::isUpperCase)
|| !value.chars().anyMatch(Character::isDigit)) {
throw new AssertionError("generated password violates the policy");
}
}
No Java project required
If you need a password rather than source code, use the browser password generator. It runs locally with the Web Crypto API and provides length, compatibility, and exclusion controls. For Python code, use the Python password generator guide.
Sources and tested scope
The complete class and policy checks were compiled and executed with OpenJDK 11 on October 2, 2026. The APIs remain documented in current Java SE releases.