Secure Random Password Generator for Developers and API Keys
A secure random password generator built for developers — entropy explained, why Math.random() is unsafe for secrets, and a free client-side tool.
Try it now: Password Generator — Generate strong random passwords and passphrases with a computed entropy readout — unbiased, cryptographically random, never transmitted.
Strength Is Entropy, Not a Complexity Checklist
“At least one uppercase letter, one number, one symbol” is a rule about surface appearance, and it's a poor proxy for what actually resists guessing: entropy, measured in bits. A secure random password generator for developers should be judged on that number, not on whether it satisfies a checklist a form designer invented in 2009. Entropy answers one question — how many equally likely passwords could a random draw have produced — and every bit doubles that count. A password generator that reports its entropy is telling you something real; one that just enforces character classes is telling you almost nothing.
The formula is exactly log2(character-set size ^ length), which simplifies to length × log2(character-set size). A 94-character set (upper, lower, digits, and printable symbols) contributes about 6.55 bits per character, so length is doing almost all the remaining work — and that's the one lever a password generator gives you direct control over.
The Math: 8 Characters vs. 12 Characters
Two random passwords from the same 94-character set, differing only in length, don't differ by a little — they differ by an amount that changes how long a brute-force search takes from “plausible” to “not in this universe”s remaining lifetime.”
charset size = 94 (upper + lower + digits + symbols) log2(94) ≈ 6.554 bits per character 8-character random password: 8 × 6.554 ≈ 52.4 bits of entropy possible passwords ≈ 2^52.4 ≈ 6.1 × 10^15 12-character random password: 12 × 6.554 ≈ 78.6 bits of entropy possible passwords ≈ 2^78.6 ≈ 6.0 × 10^23 difference: 4 extra characters ≈ 2^26 times more possibilities, not 50% more — roughly 100 million times more.
That last line is the part worth internalizing: entropy is exponential in length, so each additional character from a fixed set multiplies the search space rather than adding to it. This is also why a strong password generatorthat defaults to a short length “for convenience” is quietly giving away most of the security a longer default would have provided for free.
Passphrases: Fewer, Longer Units, Same Math
A passphrase generatorapplies the identical formula to a different alphabet — instead of drawing characters from a 94-symbol set, it draws whole words from a dictionary. If the dictionary has 7,776 words (the size of the well-known EFF word list, chosen because it's exactly 6^5, convenient for dice rolls), each word contributes log2(7776) ≈ 12.9 bits, and a passphrase of several random words adds up the same way a character password does.
word list size = 7,776
log2(7776) ≈ 12.925 bits per word
5-word random passphrase ("correct horse battery staple river"):
5 × 12.925 ≈ 64.6 bits of entropy
possible passphrases ≈ 2^64.6 ≈ 2.5 × 10^19
6-word random passphrase:
6 × 12.925 ≈ 77.5 bits — comparable to the 12-char password above
...but 5-6 words are far easier for a human to actually
read, type, and recall correctly than a random character string
of similar entropy.The tradeoff is legibility, not security: a random random password and a random passphrase at the same bit count are equally hard to guess. The passphrase just happens to be dramatically easier to type correctly on a phone keyboard or read aloud over a phone call, which is the entire reason it exists as an option rather than a novelty.
For Developers, the Password Is Never Typed — So Maximize the Character Set
Memorability stops mattering the moment a value is generated once, copy-pasted into a secrets manager or an environment variable, and never typed by a human again. An API key, a database password, a JWT signing secret, a Redis AUTH string — these are exactly the case a secure random password generator for developersis built for, and the right default is the widest safe character set at a generous length, because there's no memorability cost to pay in exchange for the extra bits.
- API keys and signing secrets: maximize the character set (letters, digits, and symbols that the target system accepts) and length — 32+ random characters, generated once, stored in a secrets manager, rotated on a schedule.
- Database passwords: the same logic applies, minus whatever characters the connection string format or the database driver mishandles — check for URL-unsafe or shell-unsafe symbols before generating if the value gets embedded in a connection URI.
- Human-memorized credentials:this is the one case where a passphrase genuinely outperforms a random string of equivalent entropy — it's the only scenario where a person, not a clipboard, has to reproduce the value.
The related question of how these secrets are stored and verified — hashing, not encrypting, credentials before they touch a database — is covered in full in the Hash Generator guide, alongside GenKitLab's Hash Generator.
The One Correctness Point: Where the Randomness Comes From
The one thing worth being exact about: a password generator has to draw from a cryptographically secure random source — crypto.getRandomValues() in the browser, not Math.random(). Math.random()is a fast, non-cryptographic pseudo-random number generator; its output is unsuitable for anything security-sensitive, and in some engines it's seedable or predictable enough to be a real weakness, not a theoretical one.
The second, subtler failure is bias in how a random number gets mapped to a character. A naive randomIndex = randomNumber % charsetLengthintroduces a measurable skew whenever the charset length doesn't evenly divide the range of the random source, because the top of the range gets mapped to a slightly smaller slice of characters than the bottom does. That skew is small per character, but it compounds — the effective entropy of the resulting password ends up lower than length × log2(charset size)suggests, even though every character in the output still looks uniformly random to the eye. Rejection sampling (discarding and re-drawing values that would land in the biased remainder) is the standard fix, and it's the kind of detail that never shows up in a password just by looking at it.
// biased: modulo introduces skew unless charset.length evenly divides 256
const index = crypto.getRandomValues(new Uint8Array(1))[0] % charset.length;
// unbiased: reject and re-draw values that would skew the distribution
function unbiasedIndex(charsetLength: number): number {
const max = 256 - (256 % charsetLength); // largest multiple of charsetLength ≤ 256
let byte: number;
do {
byte = crypto.getRandomValues(new Uint8Array(1))[0];
} while (byte >= max);
return byte % charsetLength;
}GenKitLab's Password Generator generates strong random passwords and passphrases with a computed entropy readout, draws exclusively from crypto.getRandomValues() with unbiased character selection, and runs entirely client-side — nothing you generate is ever transmitted anywhere.
Frequently asked questions
›What actually makes a password strong — length, symbols, or something else?
Entropy, measured in bits, is what matters — and it's driven far more by length than by which character classes are included. A 12-character random password from a 94-character set has roughly 2^26 (about 100 million) times more possible combinations than an 8-character password from the same set, purely from those 4 extra characters.
›How is password entropy calculated?
entropy (in bits) = length × log2(character-set size). An 8-character password from a 94-character set (upper, lower, digits, symbols) has about 52.4 bits of entropy; a 12-character password from the same set has about 78.6 bits. Each additional character multiplies the search space rather than adding to it.
›Is a passphrase more secure than a random password?
Neither is inherently more secure — the same entropy formula applies to both, just with a different alphabet (dictionary words instead of characters). A 6-word passphrase from a 7,776-word list has entropy comparable to a 12-character random password. The real difference is legibility: a passphrase is dramatically easier for a human to type and recall at the same bit count.
›Why does entropy matter more than memorability for API keys and database passwords?
Because those values are generated once and copy-pasted into a secrets manager or environment variable — a human never types them again. There's no memorability cost to trade away, so a generator should default to the widest safe character set and a generous length rather than optimizing for anything a person needs to recall.
›Is Math.random() safe to use for generating passwords?
No. Math.random() is a fast, non-cryptographic pseudo-random number generator not designed for security-sensitive use, and its output can be predictable enough in some engines to be a real weakness. A password generator should use crypto.getRandomValues() instead, which draws from the operating system's cryptographically secure random source.
›Can a password generator produce weaker output even if it uses a cryptographically secure random source?
Yes, if it maps random values to characters with a naive modulo operation. When the character-set length doesn't evenly divide the random source's range, modulo introduces a small but measurable bias toward certain characters, lowering the effective entropy below what length × log2(charset size) suggests. Correct implementations use rejection sampling to discard values that would introduce that skew.
Last updated