Why bcrypt: The History of Password Hashing, Cost Factors, and When Argon2 Is Better
SHA-1 and MD5 are fast by design β which is why GPUs crack them in hours after a breach. bcrypt's deliberate slowness and automatic salting are its defence. Here's how bcrypt works, the 72-byte limit, choosing a cost factor, and when Argon2 is the better choice.
By sadiqbd Β· June 9, 2026
Every major password breach follows the same pattern β and bcrypt is one of the few defences that holds
In 2012, LinkedIn was breached. 117 million passwords were leaked. They were hashed with SHA-1 without salt. Within days, the majority were cracked. SHA-1 is fast β GPUs can compute billions of SHA-1 hashes per second. With a good GPU and common password dictionaries, cracking an unsalted SHA-1 hash takes seconds.
bcrypt was designed specifically to make this economically prohibitive. Understanding why it works β and when Argon2 is the better choice β is one of the more important security decisions in any application that stores credentials.
Why fast hash functions fail for passwords
MD5, SHA-1, SHA-256, and SHA-3 are designed to be fast. A modern GPU can compute hundreds of billions of SHA-256 hashes per second. This speed is a feature for their intended uses (file integrity verification, digital signatures) and a critical weakness for password storage.
The attack: obtain the hashed passwords from a breach. Run dictionary words, common password patterns, and variations through the hash function. Compare each output to the leaked hashes. Any match reveals the original password.
At a trillion guesses per second (achievable with a high-end GPU cluster), an 8-character password using all printable ASCII (95 characters, 95βΈ β 6.6 Γ 10ΒΉβ΅ possibilities) takes about 6,600 seconds β under 2 hours.
How bcrypt works
bcrypt was designed by Niels Provos and David Mazières in 1999 with two specific properties that defeat GPU cracking:
Adjustable work factor (cost): bcrypt's algorithm runs a configurable number of iterations. The work factor (typically called cost or rounds, specified as a base-2 exponent) determines how slow the hash computation is. Cost 10 = 2ΒΉβ° = 1,024 iterations. Each increment of the cost factor doubles the time required.
At cost 10:
- Compute time per hash: ~100ms on modern hardware
- Hashes per second on a GPU: ~10,000
At cost 12:
- Compute time: ~400ms
- Hashes per second on a GPU: ~2,500
The work factor makes dictionary attacks impractical: at 2,500 hashes per second, testing a dictionary of 10 billion common passwords takes 4 million seconds β 46 days. This cost can be increased as hardware improves.
Salting (built-in): bcrypt automatically generates a random salt for each password. The salt is incorporated into the hash and stored alongside it. Two users with the same password produce different hashes.
Without salting, an attacker can precompute a "rainbow table" β a dictionary of pre-hashed passwords β and look up hash outputs instantly. Salting makes precomputation impossible: you'd need a separate rainbow table for every possible salt value.
The bcrypt output format
$2b$12$somerandomsalt22chars.hashoutput31chars
Decoded:
$2b$β bcrypt version identifier12β the cost factor (work factor)somerandomsalt22charsβ the 22-character Base64-encoded salthashoutput31charsβ the 31-character hash output
The entire 60-character string is stored in the database and contains everything needed to verify a future password attempt.
Verification process:
- User submits password
- Extract the salt and cost factor from the stored hash
- Run bcrypt with the same salt and cost factor on the submitted password
- Compare the output to the stored hash
- Match = correct password; no match = incorrect
Choosing a cost factor
The rule of thumb: choose the highest cost factor that keeps login time acceptable (typically under 100β200ms for interactive login, up to 1 second for high-security contexts).
| Cost | Approx. compute time | Suitable for |
|---|---|---|
| 10 | ~65ms | Standard web app login |
| 11 | ~130ms | Slightly higher security |
| 12 | ~250ms | Recommended new default |
| 13 | ~500ms | High-security accounts |
| 14 | ~1 second | Maximum practical for interactive use |
Higher cost factors slow down legitimate login (marginally) and dramatically slow down attacker cracking. The asymmetry favours the defender.
Upgrade the cost factor over time: as hardware improves, bcrypt's effective security decreases. Re-hash passwords with higher cost factors when users log in β the current password is available at login, allowing rehashing with a higher cost before storing.
bcrypt's limitations
Maximum password length: bcrypt truncates inputs at 72 bytes (72 ASCII characters). Passwords longer than 72 characters are treated as identical β "password1234...73chars" and "password1234...73charsDIFFERENT" would hash to the same value.
Mitigation: pre-hash the password with SHA-256 before passing to bcrypt, converting arbitrarily long inputs to 32 bytes. This removes the 72-byte truncation:
import bcrypt, hashlib
def hash_password(password: str) -> bytes:
# Pre-hash to remove length limit
pre_hashed = hashlib.sha256(password.encode()).hexdigest()
return bcrypt.hashpw(pre_hashed.encode(), bcrypt.gensalt(rounds=12))
Argon2: the modern recommendation
Argon2 won the Password Hashing Competition in 2015 and is the current recommendation from OWASP and most security researchers for new systems.
Three variants:
argon2d: resistant to GPU attacks (uses data-dependent memory access)argon2i: resistant to side-channel attacks (data-independent, safer for some server environments)argon2id: hybrid, recommended as the default
Argon2's advantages over bcrypt:
- Memory hardness: Argon2 can be configured to require a large amount of memory during computation. GPUs have limited per-core memory; memory-hard algorithms dramatically reduce the number of parallel attacks a GPU can run simultaneously. bcrypt is primarily time-hard, not memory-hard.
- No password length limit: no 72-byte truncation.
- Modern design: bcrypt was designed in 1999 for hardware of that era; Argon2 was designed for current threat models.
For new systems in 2024: Argon2id with parameters tuned to ~100ms on your target hardware is the recommended choice. For existing bcrypt systems, bcrypt at cost 12+ remains good β migration to Argon2 is worthwhile but not urgent.
How to use the Bcrypt Generator on sadiqbd.com
- Enter the password to hash
- Set the cost factor β 12 is a good default for most applications
- Generate β the tool produces a bcrypt hash with an embedded random salt
- Verify β paste an existing bcrypt hash and a candidate password to verify they match
Frequently Asked Questions
Should I be concerned about bcrypt's 72-byte limit in practice? Most users never set passwords longer than 72 bytes. If your application allows very long passphrases (32+ words), the truncation is worth addressing with pre-hashing. For typical password policies (8β32 characters), it's not a practical concern.
Is it safe to use bcrypt for new applications in 2024? Yes β bcrypt at cost 12 or higher remains secure for password storage. Argon2id is technically superior, but bcrypt with an appropriate cost factor is not a security risk. The choice is between "good" (bcrypt) and "better" (Argon2id).
Is the Bcrypt Generator free? Yes β completely free, no sign-up required.
The history of password breaches is a history of fast hash functions being applied to human-predictable passwords. bcrypt's deliberate slowness and automatic salting make it a different category of defence.
Try the Bcrypt Generator free at sadiqbd.com β hash and verify passwords with bcrypt, with configurable cost factors.