Java Password Generator: Configurable Length, Symbols & Strength Levels
Strong, unique passwords are essential for security. This article shows how to build a configurable Java password generator that supports adjustable length, inclusion/exclusion of symbol sets, and selectable strength levels (weak, medium, strong). You’ll get a clear design, a secure implementation using Java’s cryptographic RNG, and examples showing how to use and extend the generator.
Design overview
- Inputs: desired length (int), character set options (uppercase, lowercase, digits, symbols), strength level (weak, medium, strong).
- Outputs: a randomly generated password string meeting the requested options.
- Constraints: enforce minimum/maximum lengths and guarantee at least one character from each selected category when strength requires it.
- Security: use SecureRandom (java.security.SecureRandom) for non-predictable randomness; avoid java.util.Random.
Character sets
- Lowercase letters: abcdefghijklmnopqrstuvwxyz
- Uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
- Digits: 0123456789
- Symbols (example set): !@#\(%^&*()-_=+[]{};:,.<>?/</li> </ul> <p>You can customize the symbol set to match your policy (e.g., allow only keyboard-safe characters).</p> <h3>Strength levels (recommended behavior)</h3> <ul> <li><strong>Weak:</strong> shorter length (e.g., 6–8), may include only lowercase and digits. Useful for tests but not recommended for real accounts.</li> <li><strong>Medium:</strong> moderate length (e.g., 10–12), includes lowercase, uppercase, and digits.</li> <li><strong>Strong:</strong> longer length (>= 14), includes lowercase, uppercase, digits, and symbols. Enforce at least one character from each selected category.</li> </ul> <h3>Java implementation</h3> <pre><div class="XG2rBS5V967VhGTCEN1k"><div class="nHykNMmtaaTJMjgzStID"><div class="HsT0RHFbNELC00WicOi8"><i><svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M15.434 7.51c.137.137.212.311.212.49a.694.694 0 0 1-.212.5l-3.54 3.5a.893.893 0 0 1-.277.18 1.024 1.024 0 0 1-.684.038.945.945 0 0 1-.302-.148.787.787 0 0 1-.213-.234.652.652 0 0 1-.045-.58.74.74 0 0 1 .175-.256l3.045-3-3.045-3a.69.69 0 0 1-.22-.55.723.723 0 0 1 .303-.52 1 1 0 0 1 .648-.186.962.962 0 0 1 .614.256l3.541 3.51Zm-12.281 0A.695.695 0 0 0 2.94 8a.694.694 0 0 0 .213.5l3.54 3.5a.893.893 0 0 0 .277.18 1.024 1.024 0 0 0 .684.038.945.945 0 0 0 .302-.148.788.788 0 0 0 .213-.234.651.651 0 0 0 .045-.58.74.74 0 0 0-.175-.256L4.994 8l3.045-3a.69.69 0 0 0 .22-.55.723.723 0 0 0-.303-.52 1 1 0 0 0-.648-.186.962.962 0 0 0-.615.256l-3.54 3.51Z"></path></svg></i><p class="li3asHIMe05JPmtJCytG wZ4JdaHxSAhGy1HoNVja cPy9QU4brI7VQXFNPEvF">java</p></div><div class="CF2lgtGWtYUYmTULoX44"><button type="button" class="st68fcLUUT0dNcuLLB2_ ffON2NH02oMAcqyoh2UU MQCbz04ET5EljRmK3YpQ CPXAhl7VTkj2dHDyAYAf" data-copycode="true" role="button" aria-label="Copy Code"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M9.975 1h.09a3.2 3.2 0 0 1 3.202 3.201v1.924a.754.754 0 0 1-.017.16l1.23 1.353A2 2 0 0 1 15 8.983V14a2 2 0 0 1-2 2H8a2 2 0 0 1-1.733-1H4.183a3.201 3.201 0 0 1-3.2-3.201V4.201a3.2 3.2 0 0 1 3.04-3.197A1.25 1.25 0 0 1 5.25 0h3.5c.604 0 1.109.43 1.225 1ZM4.249 2.5h-.066a1.7 1.7 0 0 0-1.7 1.701v7.598c0 .94.761 1.701 1.7 1.701H6V7a2 2 0 0 1 2-2h3.197c.195 0 .387.028.57.083v-.882A1.7 1.7 0 0 0 10.066 2.5H9.75c-.228.304-.591.5-1 .5h-3.5c-.41 0-.772-.196-1-.5ZM5 1.75v-.5A.25.25 0 0 1 5.25 1h3.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-3.5A.25.25 0 0 1 5 1.75ZM7.5 7a.5.5 0 0 1 .5-.5h3V9a1 1 0 0 0 1 1h1.5v4a.5.5 0 0 1-.5.5H8a.5.5 0 0 1-.5-.5V7Zm6 2v-.017a.5.5 0 0 0-.13-.336L12 7.14V9h1.5Z"></path></svg>Copy Code</button><button type="button" class="st68fcLUUT0dNcuLLB2_ WtfzoAXPoZC2mMqcexgL ffON2NH02oMAcqyoh2UU MQCbz04ET5EljRmK3YpQ GnLX_jUB3Jn3idluie7R"><svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" fill-rule="evenodd" d="M20.618 4.214a1 1 0 0 1 .168 1.404l-11 14a1 1 0 0 1-1.554.022l-5-6a1 1 0 0 1 1.536-1.28l4.21 5.05L19.213 4.382a1 1 0 0 1 1.404-.168Z" clip-rule="evenodd"></path></svg>Copied</button></div></div><div class="mtDfw7oSa1WexjXyzs9y" style="color: var(–sds-color-text-01); font-family: var(–sds-font-family-monospace); direction: ltr; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; font-size: var(–sds-font-size-label); line-height: 1.2em; tab-size: 4; hyphens: none; padding: var(–sds-space-x02, 8px) var(–sds-space-x04, 16px) var(–sds-space-x04, 16px); margin: 0px; overflow: auto; border: none; background: transparent;"><code class="language-java" style="color: rgb(57, 58, 52); font-family: Consolas, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; direction: ltr; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; font-size: 0.9em; line-height: 1.2em; tab-size: 4; hyphens: none;"><span class="token" style="color: rgb(0, 0, 255);">import</span><span> </span><span class="token">java</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token">security</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(43, 145, 175);">SecureRandom</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span></span><span class="token" style="color: rgb(0, 0, 255);">import</span><span> </span><span class="token">java</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token">util</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(43, 145, 175);">ArrayList</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span></span><span class="token" style="color: rgb(0, 0, 255);">import</span><span> </span><span class="token">java</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token">util</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(43, 145, 175);">Collections</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span></span><span class="token" style="color: rgb(0, 0, 255);">import</span><span> </span><span class="token">java</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token">util</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(43, 145, 175);">List</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span> <span></span><span class="token" style="color: rgb(0, 0, 255);">public</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">class</span><span> </span><span class="token" style="color: rgb(43, 145, 175);">PasswordGenerator</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">{</span><span> </span><span></span><span class="token" style="color: rgb(0, 0, 255);">private</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">static</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">final</span><span> </span><span class="token" style="color: rgb(43, 145, 175);">String</span><span> LOWER </span><span class="token" style="color: rgb(57, 58, 52);">=</span><span> </span><span class="token" style="color: rgb(163, 21, 21);">"abcdefghijklmnopqrstuvwxyz"</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> </span><span class="token" style="color: rgb(0, 0, 255);">private</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">static</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">final</span><span> </span><span class="token" style="color: rgb(43, 145, 175);">String</span><span> UPPER </span><span class="token" style="color: rgb(57, 58, 52);">=</span><span> </span><span class="token" style="color: rgb(163, 21, 21);">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> </span><span class="token" style="color: rgb(0, 0, 255);">private</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">static</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">final</span><span> </span><span class="token" style="color: rgb(43, 145, 175);">String</span><span> DIGITS </span><span class="token" style="color: rgb(57, 58, 52);">=</span><span> </span><span class="token" style="color: rgb(163, 21, 21);">"0123456789"</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> </span><span class="token" style="color: rgb(0, 0, 255);">private</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">static</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">final</span><span> </span><span class="token" style="color: rgb(43, 145, 175);">String</span><span> SYMBOLS </span><span class="token" style="color: rgb(57, 58, 52);">=</span><span> </span><span class="token" style="color: rgb(163, 21, 21);">"!@#\)%^&*()-=+[]{};:,.<>?/”;
private final SecureRandom random = new SecureRandom();
public enum Strength { WEAK, MEDIUM, STRONG }
public String generate(int length, boolean useUpper, boolean useLower,
boolean useDigits, boolean useSymbols, Strength strength) {
if (length < 1) throw new IllegalArgumentException(“length must be >= 1”);
StringBuilder allowed = new StringBuilder();
if (useLower) allowed.append(LOWER);
if (useUpper) allowed.append(UPPER);
if (useDigits) allowed.append(DIGITS);
if (useSymbols) allowed.append(SYMBOLS);
if (allowed.length() == 0) throw new IllegalArgumentException(“No character sets selected”);
// Enforce minimums by strength
if (strength == Strength.WEAK && length < 6) length = 6;
if (strength == Strength.MEDIUM && length < 10) length = 10;
if (strength == Strength.STRONG && length < 14) length = 14;
// If strong, ensure at least one of each selected category appears
List<Character> guaranteed = new ArrayList<>();
if (strength == Strength.STRONG) {
if (useLower) guaranteed.add(randomCharFrom(LOWER));
if (useUpper) guaranteed.add(randomCharFrom(UPPER));
if (useDigits) guaranteed.add(randomCharFrom(DIGITS));
if (useSymbols) guaranteed.add(randomCharFrom(SYMBOLS));
}
// Build the rest
char[] password = new char[length];
for (int i = 0; i < length; i++) {
password[i] = allowed.charAt(random.nextInt(allowed.length()));
}
// Inject guaranteed chars into random positions
Collections.shuffle(guaranteed, random);
for (int i = 0; i < guaranteed.size() && i < password.length; i++) {
int pos = random.nextInt(length);
password[pos] = guaranteed.get(i);
}
return new String(password);
}
private char randomCharFrom(String s) {
return s.charAt(random.nextInt(s.length()));
}
// Convenience methods
public String generateByStrength(Strength strength) {
switch (strength) {
case WEAK: return generate(8, false, true, true, false, strength);
case MEDIUM: return generate(12, true, true, true, false, strength);
default: return generate(16, true, true, true, true, strength);
}
}
}
Leave a Reply