Password Generator — Java source
Generate cryptographically-random passwords with a CSPRNG using rejection sampling (no modulo bias). Shows live entropy in bits, a 5-tier strength meter, average offline-GPU crack time, and a Pro mode with the entropy formula, a crack-time-vs-length curve, and a 4-scenario attack table. Everything runs locally - nothing is sent anywhere.
This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.
// password-generator — CSPRNG password generation + entropy scoring. Language: Java (17; java.security.SecureRandom). Port of src/lib/password.ts.
import java.security.SecureRandom;
final class PasswordGenerator {
static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static final String NUMBERS = "0123456789";
static final String SYMBOLS = "!@#$%^&*()-_=+[]{};:,.<>?/";
static final String AMBIGUOUS = "O0Il1|"; // O/0, I/l/1, pipe — dropped on request
static final SecureRandom RNG = new SecureRandom();
record PasswordOptions(int length, boolean upper, boolean lower,
boolean numbers, boolean symbols, boolean excludeAmbiguous) {}
// Concat the selected pools, then drop ambiguous glyphs (mirrors buildCharset).
static String buildCharset(PasswordOptions o) {
StringBuilder cs = new StringBuilder();
if (o.lower()) cs.append(LOWER);
if (o.upper()) cs.append(UPPER);
if (o.numbers()) cs.append(NUMBERS);
if (o.symbols()) cs.append(SYMBOLS);
if (o.excludeAmbiguous()) {
StringBuilder keep = new StringBuilder(cs.length());
for (int i = 0; i < cs.length(); i++) {
char c = cs.charAt(i);
if (AMBIGUOUS.indexOf(c) < 0) keep.append(c);
}
return keep.toString();
}
return cs.toString();
}
// Uniform index in [0, n): reject uint32 SecureRandom draws >= the largest
// multiple of n fitting in 2^32, so `% n` carries no modulo bias.
static int unbiasedIndex(int n) {
long max = 1L << 32, limit = max - max % n, r;
do { r = RNG.nextInt() & 0xFFFFFFFFL; } while (r >= limit);
return (int) (r % n);
}
// Returns "" for an empty pool or length < 1 — same contract as the TS lib.
static String generate(PasswordOptions o) {
String cs = buildCharset(o);
if (cs.isEmpty() || o.length() < 1) return "";
StringBuilder pw = new StringBuilder(o.length());
for (int i = 0; i < o.length(); i++) pw.append(cs.charAt(unbiasedIndex(cs.length())));
return pw.toString();
}
// Theoretical entropy in bits: length * log2(|alphabet|).
static double entropyBits(int length, int charsetSize) {
return length <= 0 || charsetSize <= 1 ? 0.0 : length * Math.log(charsetSize) / Math.log(2);
}
// Strength meter tiers, 1:1 with the TS thresholds.
static String strengthTier(double bits) {
return bits >= 100 ? "very strong" : bits >= 70 ? "strong"
: bits >= 45 ? "fair" : bits >= 28 ? "weak" : "very weak";
}
// Average crack time (s) = 2^(bits-1) / guesses-per-second.
static double crackTimeSeconds(double bits, double guessesPerSecond) {
return Math.pow(2, bits - 1) / guessesPerSecond;
}
public static void main(String[] args) {
var o = new PasswordOptions(20, true, true, true, true, true);
String cs = buildCharset(o);
double bits = entropyBits(o.length(), cs.length());
System.out.println(generate(o) + " — " + bits + " bits, " + strengthTier(bits));
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →