What bcrypt does and why it matters
Bcrypt is a password hashing algorithm designed to make it expensive for attackers to recover passwords from stolen hashes. Instead of encrypting, bcrypt applies a deliberately slow, adaptive function to a password combined with a unique salt so that each stored hash is expensive to compute and different even for identical passwords. That design raises the cost of brute-force and dictionary attacks: an adversary trying millions of guesses must expend significant CPU time for every attempt, which helps protect user accounts when a credential database is leaked.
Key security features of bcrypt
Several built-in features are responsible for bcrypt’s continued use in many systems. First, bcrypt uses a per-password salt so two identical passwords produce different hashes and precomputed tables (rainbow tables) are ineffective. Second, bcrypt includes a configurable cost parameter (often called the work factor) that scales the computation exponentially; increasing this parameter makes hashing slower and therefore raises the resources required for offline cracking. Third, the canonical bcrypt output encodes version, cost, salt and hash in a single string, which makes storage and verification straightforward when you use standard libraries.
How the cost factor works
The cost is expressed as a base-2 log; a cost of 12 means the underlying operation runs 2^12 iterations of the expensive key setup. This exponential relationship makes it easy to tune bcrypt over time: as hardware gets faster, raise the cost to keep hashing latency within a target range. The recommended approach is to measure how long a hash takes on your production hardware and pick a cost that yields a balance between user experience (login delays) and security. Many teams aim for single-digit to low-hundreds of milliseconds per hash, but the exact value should reflect your scale and threat model.
Known limitations and attack surface
Bcrypt is not perfect and understanding its limitations helps you apply it safely. It is not memory-hard, which means GPUs and specialized hardware gain a relative advantage over CPUs when performing massive parallel cracking. Compared with newer designs like Argon2, bcrypt is less resistant to highly parallelized attacks. Another practical issue is input handling: many bcrypt implementations truncate passwords longer than 72 bytes, which can lead to surprising behavior if applications accept very long passphrases. Finally, while bcrypt defends against offline brute force, it does not replace other layers of defense , rate limiting, multi-factor authentication, and monitoring are still necessary to mitigate online attacks or account takeover.
Best practices for secure use of bcrypt
Use a well-maintained library rather than writing your own implementation, and ensure the library supports current bcrypt variants (for example, $2b$). Always rely on a cryptographically secure random generator for salt creation; don’t invent your own salt scheme. Choose a cost factor after benchmarking on production-like hardware and plan to re-evaluate periodically. When a user successfully authenticates, consider rehashing the password with an increased cost if you’ve raised your target. Compare hashes using constant-time comparison functions to avoid timing attacks when checking credentials.
There are also practical steps for edge cases: if your application must accept very long passwords or support complex Unicode input, normalize and consistently encode the password before hashing, and if you need to accept inputs longer than 72 bytes, pre-hash the input with a secure hash (for example SHA-256) and pass that fixed-length output to bcrypt. Some teams add a server-side “pepper” (a secret stored outside the database) to provide an additional layer of protection; if you use a pepper, manage it like any other secret and plan for rotation in case of compromise.
Implementation checklist
- Use a vetted bcrypt library and keep it updated.
- Benchmark and set a cost that yields acceptable latency on your infrastructure.
- Store the full bcrypt string (version, cost, salt, hash) so you can verify and migrate later.
- Normalize and encode passwords consistently; handle Unicode carefully.
- Use constant-time comparison and secure random salts.
- Combine bcrypt with other defenses: rate limiting, MFA, monitoring, and account lockout policies.
When to consider alternatives
For new systems, consider algorithms designed to be memory-hard, such as Argon2, if your threat model includes attackers with GPUs or custom hardware. Memory-hard functions force an attacker to consume lots of memory per guess, which reduces the effectiveness of parallel GPU cracking. That said, bcrypt remains widely supported and well-understood , migrating to a different algorithm requires careful planning so you don’t break authentication or lose the ability to verify existing accounts. A common migration path is to verify with the existing algorithm at login and then rehash the plain password with the new algorithm after successful authentication.
Migrating older hashes safely
When migrating from another hashing scheme, implement a strategy that preserves user access and gradually upgrades accounts. The typical pattern is: on user login, verify the password with the old hash; if it succeeds, compute a new hash using bcrypt (or your chosen algorithm) and store it. This approach avoids forcing a password reset for all users and ensures high-value accounts move to the stronger scheme opportunistically. Keep careful logs and ensure any migration code is covered by tests so you don’t accidentally lock out users.
Summary
Bcrypt is a proven password hashing choice that uses salts and an adjustable cost factor to make offline attacks expensive. Its design emphasizes adaptability over time, but it is not memory-hard and has practical limits such as input truncation. Secure use requires selecting an appropriate cost, using well-maintained libraries, normalizing inputs, and combining bcrypt with other security controls like rate limits and multi-factor authentication. For new systems with strong GPU-based attack concerns, evaluate modern alternatives such as Argon2 while planning a careful migration path for existing hashes.
FAQs
Is bcrypt still secure in 2025?
Yes, bcrypt remains a secure option for password hashing when used correctly (appropriate cost, secure salts, proper libraries). However, if your threat model includes attackers with powerful GPUs or specialized hardware, consider using a memory-hard algorithm like Argon2 for improved resistance to parallelized cracking.
What cost factor should I use for bcrypt?
There is no single correct value; choose a cost that results in acceptable hashing time on your production hardware. Many teams aim for roughly 100–500 milliseconds per hash for interactive logins, but you should benchmark and consider your user load. Increase the cost over time as hardware improves.
Does bcrypt protect against GPU cracking?
Bcrypt slows GPU cracking compared with raw hashes because of its computational cost, but it is not memory-hard and therefore less resistant to GPUs and ASICs than algorithms like Argon2 or scrypt. Bcrypt remains useful, but accept that attackers with strong hardware will still be able to make progress given enough time and resources.
How do I handle passwords longer than 72 bytes?
Many bcrypt implementations truncate at 72 bytes. If you need to support longer passphrases consistently, pre-hash the password with a secure hash function (e.g., SHA-256) and then feed the fixed-length result to bcrypt. Also normalize Unicode input so different encodings don’t change the hash unexpectedly.
Should I add a pepper to bcrypt hashes?
A pepper (a server-side secret added to each password before hashing) can increase resilience if your database is leaked, but it introduces operational complexity: the pepper must be stored and rotated securely outside the database. Use a pepper only if you can manage it safely, and treat it like any other critical secret.