Skip to content
Security 6 min read

How to Generate Cryptographically Secure Passwords

Learn the difference between Math.random() and crypto.getRandomValues() for password generation, entropy explained, and password strength best practices for 2024.

ToolsVito Team

Math.random() Is Not Secure

Math.random() uses a pseudorandom number generator (PRNG) — an algorithm that produces a deterministic sequence from a seed. While the output looks random, a PRNG with a known or guessable seed can be predicted. In V8 (Node.js/Chrome's JS engine), Math.random() uses xorshift128+, which has been shown to be predictable from its output. Do not use it for security-sensitive applications.

crypto.getRandomValues() — The Secure Alternative

The Web Crypto API's crypto.getRandomValues() uses the operating system's entropy source (hardware events, interrupt timing, etc.) — an unpredictable source suitable for cryptographic purposes. Available in all modern browsers and Node.js (via globalThis.crypto).

// Generate 16 random bytes
const array = new Uint8Array(16);
crypto.getRandomValues(array);

// Random integer in [min, max)
function randomInt(min, max) {
  const range = max - min;
  const bytes = new Uint32Array(1);
  crypto.getRandomValues(bytes);
  return min + (bytes[0] % range);
}

Building a Password Generator

function generatePassword(length = 16, options = {}) {
  const { upper = true, lower = true, digits = true, symbols = true } = options;

  let chars = "";
  if (upper)   chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  if (lower)   chars += "abcdefghijklmnopqrstuvwxyz";
  if (digits)  chars += "0123456789";
  if (symbols) chars += "!@#$%^&*()_+-=[]{}|;:,.<>?";

  const bytes = new Uint32Array(length);
  crypto.getRandomValues(bytes);
  return Array.from(bytes, b => chars[b % chars.length]).join("");
}

Note: b % chars.length introduces a tiny bias if chars.length doesn't evenly divide 2³². For most purposes this is negligible, but for highest security use rejection sampling.

Password Entropy

Entropy measures the unpredictability of a password in bits. Higher entropy = harder to brute-force:

entropy = log2(charsetSize ^ length) = length × log2(charsetSize)
CharsetSize16 chars20 chars
Lowercase only2675 bits94 bits
Lowercase + digits3683 bits103 bits
Mixed + digits6295 bits119 bits
Full ASCII printable94105 bits131 bits

Recommendation: aim for 80+ bits of entropy for regular accounts, 128+ bits for master passwords and encryption keys.

Passphrases vs Random Passwords

A passphrase like "correct horse battery staple" (from Diceware, 4 random words from a 7776-word list) has ≈51 bits of entropy. Six words = ≈77 bits. Passphrases are memorable and can achieve high entropy, but random character passwords achieve higher entropy per character.

Password Manager Best Practices

  • Use a different password for every account.
  • Store passwords in a password manager (1Password, Bitwarden, etc.) — never in spreadsheets or plain text files.
  • Enable two-factor authentication on your password manager and high-value accounts.
  • Use 16+ character passwords for most accounts; 20+ for critical accounts.
  • Include all character types unless the site explicitly forbids some.

Generate a Secure Password Now

Use ToolsVito's Password Generator — powered by crypto.getRandomValues(), runs entirely in your browser, and never transmits the generated password anywhere.

Try it now — free, runs in your browser

Password Generator

Strong, random passwords