In one sentence
bcrypt is a password-hashing algorithm designed to be slow on purpose, so that even if a database of hashes leaks, brute-forcing the original passwords is expensive at scale.
Why it matters
A fast hash (plain SHA-256, MD5) is the wrong tool for passwords — a GPU rig tries tens of billions of guesses a second against a fast hash, but only tens of thousands against bcrypt, because bcrypt is deliberately tunable to cost more CPU time per attempt (the "work factor" or "cost" parameter). This is the single most common password-storage mistake worth knowing how to spot: a site storing SHA-256(password) instead of bcrypt(password) has effectively no protection once the hash list leaks, and the leak will be run against every other site the users share passwords with.
It is also a compliance item: PCI DSS requirement 8.3.2 requires passwords to be rendered unreadable with strong cryptography, and every modern guideline (NIST SP 800-63B, OWASP) names a deliberately slow, salted algorithm.
How it works, briefly
Each bcrypt hash embeds its own salt and cost factor in the output string, so verification needs no separate lookup — the hash is self-describing:
$2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
│ │ │ │
│ │ └ 22-char salt └ 31-char hash
│ └ cost 12 → 2^12 = 4,096 rounds
└ algorithm version
Raising the cost by one doubles the computation time; the usual target is 250–500 ms per hash on your login servers, which lands around cost 10–12 today and gets bumped as hardware improves — an old hash keeps working (its cost is in the string) and can be re-hashed at the user's next login. Two limits to know: bcrypt only uses the first 72 bytes of the password (pre-hash or cap the length — and know that this once let a long-password bug hide a NUL truncation), and the $2a$ / $2b$ / $2y$ prefixes are implementation variants, all verifiable by a current library.
Argon2id (the 2015 Password Hashing Competition winner) is the current first choice for new systems because it is also memory-hard, which blunts GPU and ASIC attacks; scrypt is the older memory-hard option; PBKDF2 is acceptable where FIPS compliance forces it, with a very high iteration count. bcrypt remains perfectly sound — the sin is not "bcrypt instead of Argon2", it is "SHA-256 instead of either".
Try it yourself hands-on
Checking how your own hashing setup compares, and what a leaked hash tells you:
- Open the Password Security Suite and use its bcrypt mode to hash a sample password. Read the cost factor out of the output (
$2b$12$…). That number is what to match against current guidance — 10 as a floor, 12 as a comfortable default — rather than the library default from the year the codebase was written. - Hash the same string with a fast hash in the Hash Toolkit (SHA-256). It is instant. That difference in effort, multiplied by a billion guesses, is the entire argument for bcrypt on passwords — and against bcrypt for anything else: do not use it to checksum a file, that is what the fast, purpose-built hash function is for.
- Found a hash in a breach dump or a legacy table? Paste it into the Password Hash Verifier: it identifies the algorithm from the prefix and format (bcrypt, Argon2, a bare hex digest) and can verify a candidate password against it in your browser. A column of 32-character hex strings is MD5 and should be a P1 ticket; a column of
$argon2id$strings is fine. - Write the policy side down: the Password Policy Tester scores your password rules against NIST 800-63B, which is where "store with a slow salted hash, drop the forced rotation" is written.
Common misreadings
- bcrypt is not encryption. Nobody, including you, can recover the password from the hash; "we encrypt passwords" is either a misstatement or a real problem.
- Salting is not enough by itself. A salted SHA-256 stops rainbow tables but not brute force; the slowness is the protection.
- Peppering is a separate layer. A server-side secret mixed in before hashing (kept out of the database) protects against a database-only leak; it complements bcrypt, it does not replace it.