Password Generators Starter Kit 2026

2026-03-27 · SPUNK13 · spunk.bet

Entropy is the only number that matters

Password strength is not a colour bar. It is log2(alphabet_size ^ length), and it only holds if every character was chosen independently and uniformly at random. Choose the words yourself and the maths collapses, because a human picking "correct horse battery staple" is sampling from a much smaller and heavily skewed set than the generator would.

RecipeMathsEntropy
4 diceware words, 7776-word listlog2(77764)~51.7 bits
6 diceware wordslog2(77766)~77.5 bits
12 chars, 94-char printable ASCII set12 × log2(94)~78.7 bits
16 chars, same set16 × log2(94)~104.9 bits
20 chars, lowercase only20 × log2(26)~94 bits

Useful reference points: four diceware words are fine for a low-value forum account, and are a reasonable choice for anything you must type from memory on a TV remote. Anything guarding money, mail or infrastructure should be a generated 16-plus character string that lives in a manager and never gets typed. The bottom row makes the point that length beats character-class gymnastics — twenty lowercase letters outrun twelve characters of mixed symbol soup, and are far easier to read aloud.

Generators you already have installed

# 24 random bytes, base64 -> 32 chars, ~192 bits
openssl rand -base64 24

# hex, good for API keys and secrets in env files
openssl rand -hex 32

# 20 chars, secure mode, no ambiguous characters
pwgen -sBy 20 1

# passphrase from the system dictionary
shuf -n 5 --random-source=/dev/urandom /usr/share/dict/words | paste -sd- -

The -s flag on pwgen matters: without it, pwgen generates deliberately pronounceable and therefore much weaker passwords. -B drops ambiguous characters and -y adds symbols. For the shuf recipe, check the size of your word list first with wc -l /usr/share/dict/words so you know what entropy you actually bought.

Math.random is not a password source

In every JavaScript engine, Math.random() is a fast non-cryptographic PRNG — typically xorshift128+ — with a small internal state and no security guarantee. Given enough consecutive outputs the state can be recovered and both past and future values reconstructed. Any browser-based generator that uses it is producing predictable passwords. The correct primitive is:

const ALPHA = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%^&*';
function makePassword(len = 20) {
  const out = [];
  const buf = new Uint8Array(len * 2);
  crypto.getRandomValues(buf);
  for (const b of buf) {
    if (out.length === len) break;
    if (b >= 256 - (256 % ALPHA.length)) continue; // reject to avoid modulo bias
    out.push(ALPHA[b % ALPHA.length]);
  }
  return out.join('');
}

The rejection step is not pedantry. Because 256 is not a multiple of the alphabet size, taking the remainder without rejecting the tail makes the first few characters of the alphabet slightly more likely, which is a small but free advantage to an attacker. Server-side the equivalents are secrets.choice() in Python and crypto/rand in Go, never random or math/rand.

Dealing with sites that fight you

Real-world constraints you will hit, and the workaround for each:

Generate per site, then stop thinking about it

A generator is only half a system. The other half is a manager that stores what it produced, because a unique 100-bit password per site is worthless if you cannot retrieve it. Bitwarden, 1Password and KeePassXC all ship built-in generators with length and character-class controls, so the CLI recipes above are mainly for servers, seed values and scripts. Reuse is the failure mode that actually gets people: credential-stuffing attacks replay one leaked pair against hundreds of services, and unique passwords are what contains the blast radius to a single account. If you want a comparison of the generators themselves, see our ranked breakdown.

Explore More

Free tools, guides, and resources.

Visit spunk.bet
400+ ToolsCasinoMemesAstrologyScam DB