Skip to content
LocalOnly
Developer Utilities

NIST Password Guidelines: The Rules to Use in Your App

NIST's guidance dropped the rules most sign-up forms still enforce. Here is what it recommends instead, why length beats symbols in numbers, and how to generate passwords securely in code.

Updated October 18, 20263 min readTool runs in your browser

The NIST password guidelines, in Special Publication 800-63B, are the reference most security teams follow, and they contradict many sign-up forms still in use: no forced symbols, no expiry every 90 days. The Password Generator creates strong passwords in the browser, and its page explains why length matters more than character variety. This guide is for the other side: the rules to build into an application that accepts passwords.

What the NIST password guidelines require

  • Length first. The 2025 revision requires at least 15 characters when a password is the only factor, and at least 8 when it is combined with a second factor such as an authenticator app.
  • Allow long passwords. Accept at least 64 characters, so passphrases and password managers work.
  • Accept any characters. Spaces and Unicode included. Do not silently cut or strip what the user typed.
  • No composition rules. Do not demand an uppercase letter, a digit and a symbol. Such rules push people towards predictable patterns like Summer2026!.
  • No scheduled expiry. Require a change only when there is evidence the password was exposed.
  • Check against known bad passwords. Reject new passwords that appear in lists of breached, common or obvious choices, such as the service name or password1.
  • No hints and no security questions. Both are easier to guess than the password.

Password length vs complexity in numbers

For randomly generated passwords, strength is measured in bits of entropy: length multiplied by the bits each character carries. Worked out:

8 characters from all 94 printable symbols   52.4 bits
15 lowercase letters                          70.5 bits
12 characters from all 94 printable symbols   78.7 bits
4 random words from a 7,776-word list         51.7 bits
6 random words from a 7,776-word list         77.5 bits

Fifteen lowercase letters beat eight characters with every symbol class by 18 bits, which means about 275,000 times more guesses. That is the reasoning behind length over complexity. These figures only hold for randomly generated passwords; a human-chosen Summer2026! has far less entropy than its length suggests, which is why the breached-password check matters.

Storing passwords

Never store passwords themselves, encrypted or not. Store a hash from a password hashing function designed to be slow, such as Argon2id, scrypt or bcrypt, with a unique salt per password. General-purpose hashes like SHA-256 are far too fast for this: they are built for checking files, and an attacker with a stolen database can try billions of guesses per second against them.

Generate a secure password in code

import secrets, string

alphabet = string.ascii_letters + string.digits + string.punctuation
password = "".join(secrets.choice(alphabet) for _ in range(16))
const alphabet =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";

function generatePassword(length = 16) {
  const limit = 256 - (256 % alphabet.length);
  let password = "";
  while (password.length < length) {
    const [byte] = crypto.getRandomValues(new Uint8Array(1));
    if (byte < limit) password += alphabet[byte % alphabet.length];
  }
  return password;
}

Use secrets in Python and crypto.getRandomValues in JavaScript, never random or Math.random, which are not designed to be unpredictable. The JavaScript version discards random bytes at or above the largest multiple of the alphabet size, so every character is equally likely; a plain byte % 94 would make the first characters of the alphabet slightly more common.

Frequently asked questions

Command Palette

Search for a tool or command