The algorithm in six steps
- Validate the requested length, allowed character sets, and exclusions.
- Ask a cryptographically secure random number generator (CSPRNG) for random integers.
- Map each integer to the permitted alphabet with rejection sampling so every character remains equally likely.
- If a policy requires character categories, select the required entries with the same unbiased method.
- Fill the remaining positions, then shuffle with an unbiased Fisher–Yates shuffle.
- Return the password without logging, transmitting, or storing it unless the user explicitly chooses a secure destination.
Reference pseudocode
This structure separates randomness from password-policy logic. secureRandomIndex(max) must return every integer from zero through max - 1 with equal probability.
function generatePassword(length, characterSets):
validate length and characterSets
alphabet = unique characters from all enabled sets
output = []
for each required set:
output.append(set[secureRandomIndex(set.length)])
while output.length < length:
output.append(alphabet[secureRandomIndex(alphabet.length)])
fisherYatesShuffle(output, secureRandomIndex)
return join(output)The algorithm is short because the security-critical work belongs in the random source and the unbiased mapping. Adding transformations does not repair weak randomness.
1. Use a cryptographic random source
Ordinary pseudorandom functions are designed for simulations, games, and repeatable tests—not secrets. A password generator needs a CSPRNG seeded from operating-system entropy. In a browser, the standard interface is crypto.getRandomValues(). Python provides secrets; modern server platforms expose comparable cryptographic APIs.
Math.random() for passwords. Its algorithm and internal state are not required to resist prediction. Do not invent a seed from the clock, username, device identifier, or mouse timing either.2. Avoid modulo bias
A common implementation takes a random integer and calculates value % alphabet.length. That is unbiased only when the random range divides evenly by the alphabet size. Otherwise, some characters receive one more possible input value than others.
Rejection sampling fixes this. For an unsigned 32-bit value, calculate the largest multiple of the alphabet size that does not exceed the 232 range. Discard values at or above that limit, then apply the remainder operation.
function secureRandomIndex(max) {
const range = 4294967296;
const limit = Math.floor(range / max) * max;
const value = new Uint32Array(1);
do {
crypto.getRandomValues(value);
} while (value[0] >= limit);
return value[0] % max;
}This is the core mapping used by this site. Its complete source implementation also validates bounds and reuses the function for character selection and shuffling.
3. Treat password rules as constraints
Sites often require at least one uppercase letter, lowercase letter, number, or symbol. A generator can select one entry from every required set, fill the remaining positions from the combined alphabet, and shuffle the finished result. Every individual selection and swap should still use the unbiased random-index function.
These rules alter the output distribution. The simple formula length × log2(alphabet size) exactly describes independent selection from one fixed alphabet; it should not be presented as an exact entropy result when composition rules, exclusions, templates, or human-selected text change the process. Model the actual generator policy.
Compatibility settings should remove only characters the destination rejects. Automatically shortening passwords or silently falling back to a smaller alphabet reduces the possible output space.
4. Shuffle correctly
If required characters are inserted in predictable positions, the attacker learns part of the structure. Use the Fisher–Yates algorithm, selecting each swap index uniformly from the remaining range. Sorting by a random comparator is not a correct shuffle and can introduce engine-dependent bias.
function shuffle(values) {
for (let i = values.length - 1; i > 0; i -= 1) {
const j = secureRandomIndex(i + 1);
[values[i], values[j]] = [values[j], values[i]];
}
return values;
}5. Calculate strength from the generation process
When each of A characters is independently and uniformly selected for L positions, the output space is AL and the theoretical entropy is L × log2(A) bits. For a word generator that independently selects W words from a list of size N, it is W × log2(N).
That calculation does not describe a human-created password, a quotation, a keyboard pattern, a reused credential, or a generator with unknown bias. Length alone cannot make predictable selection random.
6. Test properties, not a few outputs
A secure code review should verify the random API, mapping, policy behavior, error handling, and data flow. Useful automated tests include:
- requested lengths and enabled character sets are always respected;
- excluded and ambiguous characters never appear;
- required categories appear when the policy requests them;
- invalid lengths, empty alphabets, and impossible policies fail clearly;
- the implementation never falls back to a non-cryptographic random source;
- generated values are not placed in URLs, analytics events, logs, or browser storage;
- statistical checks can detect obvious implementation mistakes, while recognizing that passing them does not prove cryptographic security.
Generation is not hashing
A password generating algorithm creates a new secret. A password hashing algorithm protects a verifier’s stored representation of a user password. They solve different problems. Servers should not store plaintext passwords or use a fast general-purpose hash by itself; current password-storage guidance calls for a salted, costed password-hashing scheme and appropriate operational controls.
One-time password algorithms such as HOTP and TOTP are different again: they derive short-lived authentication codes from a shared secret and counter or time value. They are not substitutes for a general random password generator.
Legacy algorithms and current practice
NIST FIPS 181 documented an automated pronounceable-password generator in 1993, but NIST withdrew that standard in 2015. It is useful history, not a current implementation target. Modern software should use the platform’s supported cryptographic random interface and current authentication guidance rather than reproducing the old DES-based design.
Frequently asked questions
What is the best algorithm for generating a password?
Use the platform CSPRNG to select independent values from the allowed alphabet, remove mapping bias, and preserve as much length as the destination accepts. The random source and mapping matter more than inventing a complicated custom transformation.
Can a password algorithm use a master password and site name?
Deterministic systems can derive site-specific outputs, but their security, domain normalization, counter handling, recovery, and master-secret protection require a carefully reviewed protocol. Do not improvise one from ordinary hashes or string concatenation.
Should a generator block weak-looking random results?
A truly random result can occasionally contain a run or recognizable fragment. Repeatedly rejecting outputs based on subjective appearance changes the distribution. Apply documented compatibility or breached-password rules, not cosmetic preferences presented as cryptographic improvement.
Does open-source code make a generator secure?
No. It makes inspection possible. Security still depends on the implementation, dependencies, delivery path, runtime environment, and how the generated password is handled afterward.
Sources and review scope
Guidance and linked documentation were reviewed on September 27, 2026. This article explains design properties and this site’s implementation; it is not a certification or independent cryptographic audit.