Generated passwords fail for two opposite reasons: they look strong but come from a weak random source, or they are strong but then get stored with a fast hash as if that were "encryption." Frontend tools make generation easy; the security property still depends on entropy, character set, and where the secret goes next.
Bottom line: Use a cryptographically secure PRNG (crypto.getRandomValues), pick a character set that matches the system that will accept the password, and aim for enough entropy (typically 80+ bits for important accounts). Never use SHA-256 of a password as storage. Generators create secrets; password KDFs (Argon2, bcrypt, scrypt) protect them at rest.
Who this guide is for
Frontend and full-stack developers building signup flows, local secret helpers, or test credentials — and anyone choosing between a browser password tool and a password manager. If you only need unique IDs, use a UUID generator; passwords are for authentication secrets, not identifiers.
Entropy in plain language
Entropy measures how hard a value is to guess, usually in bits. Roughly: each extra bit doubles the search space.
For a password drawn uniformly from a set of size N with length L:
entropy_bits ≈ L × log2(N)
| Character set |
Approx. N |
Length 12 |
Length 16 |
Length 20 |
| Digits only |
10 |
~40 bits |
~53 bits |
~66 bits |
| Lowercase |
26 |
~56 bits |
~75 bits |
~94 bits |
| Lower + upper + digits |
62 |
~71 bits |
~95 bits |
~119 bits |
| Above + symbols (~95 printable) |
~95 |
~79 bits |
~105 bits |
~131 bits |
Rules of thumb used in practice:
| Use case |
Target entropy |
| Low-value throwaway account |
~64 bits |
| Normal user / API password |
80–100 bits |
| High-value master or vault secret |
128+ bits |
A long passphrase of random words can also hit these targets; the math is the same — count the size of the word list and the number of words.
Length and alphabet size both matter. Password1! is long enough on paper but fails because it is not drawn uniformly from a large space — attackers try common patterns first.
Character sets: match the consumer
Generators often offer toggles: uppercase, lowercase, digits, symbols, and "exclude ambiguous" (0/O, 1/l/I).
| Option |
When to use |
Risk |
| Alphanumeric only |
Legacy systems that reject symbols |
Need more length for same entropy |
| Full printable ASCII |
Modern password managers / APIs |
Copy-paste into shells may need quoting |
| Exclude ambiguous |
Human typing from a screen |
Slightly smaller N — compensate with length |
| No look-alikes + no symbols |
Some bank / console UIs |
Easy to under-estimate strength |
Always generate against the actual policy of the target system. A 20-character symbol-rich password that a vendor silently truncates to 12 characters is weaker than a 16-character alphanumeric password that is stored in full.
Test candidates with a Password Generator that runs in the browser so you can iterate on length and charset without sending secrets to a server.
Browser CSPRNG vs Math.random
Password generation must use a cryptographically secure random source.
| Source |
Suitable for passwords? |
Notes |
crypto.getRandomValues |
Yes |
Web Crypto; available in browsers and modern Node |
crypto.subtle (for keys) |
Yes (key generation) |
Prefer for cryptographic keys |
Math.random() |
No |
Not a CSPRNG; predictable enough to reject |
| Timestamp / UUID v1 style |
No |
Not uniform secret material |
function randomPassword(length, alphabet) {
const bytes = new Uint8Array(length);
crypto.getRandomValues(bytes);
let out = "";
// Rejection sampling avoids modulo bias when alphabet.length is not a power of 2
const maxUnbiased = Math.floor(256 / alphabet.length) * alphabet.length;
let i = 0;
while (out.length < length) {
if (i === bytes.length) {
crypto.getRandomValues(bytes);
i = 0;
}
const v = bytes[i++];
if (v < maxUnbiased) {
out += alphabet[v % alphabet.length];
}
}
return out;
}
Naive bytes[i] % alphabet.length introduces a small bias when the alphabet size does not divide 256 evenly. For short passwords the bias is minor; for high-assurance generators, use rejection sampling as above or a well-reviewed library.
codefunc's Password Generator is built for this workflow: configure charset and length, generate locally, copy once. No data leaves your machine.
Passwords vs UUIDs vs hashes
These tools solve different problems and get mixed up in tickets.
| Artifact |
Purpose |
Tool |
| Random password |
Human or machine secret for login / Basic Auth |
Password Generator |
| UUID / ULID |
Unique identifier, not a secret by default |
UUID Generator |
| SHA-256 digest |
Integrity fingerprint of known data |
Hash Generator |
A UUID is unique; it is not automatically a high-entropy password in the sense of a user-chosen secret with a charset policy — though a 128-bit random UUID can serve as an API token if the system treats it as opaque random bytes. Do not "strengthen" a password by hashing it in the client and sending the hash as the password unless the protocol is designed for that (it usually is not).
Why not for password storage hashing
Generating a strong password and storing passwords are separate layers.
| Step |
Correct approach |
Wrong approach |
| Create a secret |
CSPRNG password / passphrase |
Math.random, dictionary words alone |
| Transmit |
TLS; prefer password managers |
Paste into public pastebins |
| Store at rest (server) |
Argon2id / scrypt / bcrypt with unique salt |
SHA-256(password), MD5(password) |
| Verify |
Same KDF with stored salt and params |
Compare against a bare SHA digest table |
A Hash Generator is excellent for checksums and debugging digests. It is the wrong tool for deciding how to store user passwords. Fast hashes let stolen databases be cracked at GPU speed. OWASP and NIST guidance converge on memory-hard or intentionally slow password hashing — not a single SHA-256 pass.
If you are designing signup:
- Generate or accept a high-entropy secret.
- Send it only over HTTPS.
- On the server, run a password KDF with per-user salt and adequate parameters.
- Never log the plaintext password.
Practical workflow for developers
- Decide minimum entropy for the environment (API key vs human login).
- Pick a charset the consumer accepts; add length until bits are enough.
- Generate with
crypto.getRandomValues or a client-side Password Generator.
- Store in a password manager or secrets vault — not in git, screenshots, or chat.
- For machine tokens, consider random bytes encoded as hex/Base64 instead of "pronounceable" passwords.
- For IDs in URLs and databases, use UUID Generator — keep auth secrets separate.
Common mistakes
- Memorable patterns — keyboard walks and
SeasonYear! look complex and fall to rules-based attacks.
- Reuse across systems — one breach unlocks many accounts.
- Truncation — silent max-length on the server destroys entropy you thought you had.
- Client-only "hashing" as security — hashing in the browser before send does not replace TLS or server-side KDFs.
- Uploading secrets to online generators — prefer tools that run entirely in your browser.
Practical takeaway
Treat password generation as sampling from a known alphabet with a CSPRNG until you reach a clear entropy target. Match character sets to real system limits, and compensate with length when the alphabet shrinks. Use codefunc's Password Generator for local generation, UUID Generator for identifiers, and Hash Generator for digests — never as a password-storage strategy. Storage belongs to Argon2/bcrypt/scrypt on the server.
Sources