What bcrypt Actually Is
A Blowfish-based password hashing scheme designed by Niels Provos & David Mazières (1999). Deliberately slow and adaptive — bcrypt's cost factor lets security scale with hardware improvements.
Where bcrypt Is Used
- OpenBSD — default password hash (bcrypt originated here)
- Linux — supported via libxcrypt (
$2b$), but not the/etc/shadowdefault (SHA-512-crypt, or yescrypt on newer distros) - PHP
password_hash() - Node.js
bcrypt/bcryptjs - Django (optional backend)
- Ruby on Rails (default via
has_secure_password)
Three-Part Output Anatomy
Why bcrypt Is Slow: The Eksblowfish Key Schedule
The cost factor is not an arbitrary dial — it is literally an exponent. bcrypt runs Blowfish's key setup, then repeats it 2cost times, each round re-mixing your password and salt into an 18-word subkey array (the P-arrayThe 18 32-bit subkeys Blowfish derives from its key. In bcrypt these are re-derived every round, so the whole key schedule — not just one hash — is what gets repeated 2^cost times.) and four 256-entry substitution boxes (the S-boxesFour lookup tables of 256 32-bit words each = 4 KB of state that must be held and rewritten. This size is what makes bcrypt awkward to parallelize on a GPU's small per-core memory., 4 KB of state). That 4 KB of constantly-rewritten state is what makes bcrypt awkward to run massively-parallel on a GPU.
cost 6 → 26 = 64 key-expansion rounds
The 72-Byte Limit — bcrypt's #1 Footgun
bcrypt only feeds the first 72 bytes of a password into the key schedule. Everything after byte 72 is silently ignored. Two different passwords that share the same 72-byte prefix therefore produce a hash that verifies against either one. Type two long passwords below that agree for the first 72 bytes but differ afterward, and watch them cross-verify.
Hash Generator
Enter a password and choose a cost factor. The output is a real bcrypt hash computed in your browser — not simulated.
Input
Output
Cost Factor Timing Benchmark
Hashes the same password at cost factors 8 through 14, sequentially. Each +1 in cost doubles the computation time. This is by design — the slowness IS the security.
Results
Verify & Timing-Safe Comparison
bcrypt's headline defense is slowness + per-user salt (Exhibits 1 & 3) — that is what
survives a database breach. Constant-time comparison, shown here, is a secondary hardening:
it stops a subtler leak in how you compare the final hash. bcrypt.compare() checks a
password against a stored hash in constant time, closing a
timing oracleAn attacker who can measure how long a comparison takes and learn a secret from it. A naive byte-by-byte === returns faster on the first mismatch, so response time leaks how many leading bytes were guessed correctly..
Basic Verify
Timing Leak: This Is Why You Never Compare Hashes With ===
A naive === comparison returns as soon as it hits the first mismatched byte, so it runs
longer the more leading bytes an attacker guesses correctly. That duration is a leak.
bcrypt.compare() checks every byte regardless, so its time reveals nothing.
Honesty note: a real === leak on a modern CPU is a few nanoseconds — far too small to see on a bar. Choose how to expose it:
Naive === (variable timing)
Constant-time compare
bcrypt.compare(), HMAC tags, tokens.
But keep it in proportion: bcrypt's defining value is being deliberately slow and salted,
not the constant-time compare. That compare is the last mile of an already-strong scheme.
bcrypt vs Alternatives
Not all hashing algorithms are equal. This comparison shows why bcrypt remains a strong choice and when to prefer alternatives.
Algorithm Comparison
| Algorithm | Year | Adaptive | Memory-hard | GPU-resistant | Status |
|---|
Live Timing: bcrypt vs PBKDF2
Hash the same password with bcrypt (cost 12) and PBKDF2 (100,000 rounds via WebCrypto).
crypto.subtle.deriveBits). Native code is typically several times faster than JS for
identical work. Use this to see that both are deliberately slow — not to rank them. For the ranking,
read the work factors and the memory-hardness/GPU-resistance columns in the table above.
Real-World Attack Demo
Three breach scenarios showing what happens when passwords are stored as plaintext, unsalted MD5, or bcrypt hashes.
The button below builds a real table: it MD5s every entry in the demo's common-password wordlist, then looks each stored digest up in that table. The cells hold only the digest, so an account whose password is not in the wordlist genuinely cannot be recovered.