Skip to content

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 →