What Is Bcrypt and Why Passwords Need Slow Hashing

Passwords Should Never Be Stored as Plain Text

When you create an account on a website, the site needs a way to check your password the next time you sign in. The unsafe way is to store the password itself, in plain text, in a database. If that database is ever leaked, copied, or viewed by someone who should not see it, every password in it is exposed immediately. There is no need for an attacker to guess or crack anything, because the secrets are sitting there in readable form.

The safe approach is to store a transformed version of the password, called a hash, instead of the password itself. A hash is the output of a one-way function. It is easy to compute in one direction, from password to hash, and designed to be impractical to reverse. When you sign in, the site hashes the password you type and compares it with the stored hash. If the hashes match, the password was correct. The site never needs to store your actual password, and a leaked database does not hand attackers a list of readable passwords.

That sounds like the problem is solved, but the choice of hash function matters enormously. A fast hash designed for checking whether files have changed is a poor choice for passwords, because speed helps the attacker. This is where bcrypt comes in. Bcrypt is a password hashing function that is deliberately slow, and that slowness is its main strength.

What Is Bcrypt?

Bcrypt is a password hashing algorithm designed for storing passwords safely. It was built around the Blowfish cipher and was designed from the start for password storage, rather than adapted from a general-purpose hash. When a password is hashed with bcrypt, the output includes three pieces of information: a salt, a cost factor, and the hash itself. Those three pieces work together to make guessing slow, even for an attacker who has stolen the database.

Bcrypt is widely used in web applications, and most modern programming languages provide a well-tested bcrypt library. Developers are advised to use one of those established libraries rather than writing their own password hashing code. The details of implementation matter, and a small mistake in custom code can undo the protection that bcrypt is meant to provide.

How Bcrypt Works: Salt, Cost Factor, and Hash

Three concepts explain most of how bcrypt protects passwords.

Salt

A salt is a random value that is generated when a password is hashed. The salt is combined with the password before hashing, and it is stored alongside the hash. Its purpose is to make each hash unique, even when two users choose the same password. Without a salt, two identical passwords would produce identical hashes, which would tell an attacker that those users share a password. Worse, an attacker could precompute hashes for common passwords once and compare them against an entire database. That precomputation attack is called a rainbow table attack.

With a unique salt for each password, precomputation stops working. An attacker must attack each password separately, using its own salt. Salts do not need to be secret. They are stored in plain sight next to the hash, and that is fine, because their job is uniqueness, not secrecy. What matters is that each salt is random and is never reused across passwords.

Cost Factor

The cost factor, sometimes called the work factor, controls how much work bcrypt does. A higher cost factor means the hashing takes longer and uses more computing effort. The cost factor is stored with the hash, so the system knows how much work to do when it verifies a password later.

The cost factor is what makes bcrypt deliberately slow. A normal sign-in might take a fraction of a second, which a user barely notices. For an attacker trying millions of guesses, that same fraction of a second per guess adds up to an enormous amount of time. As computers get faster, developers can raise the cost factor for new passwords so that hashing stays slow in relative terms. This ability to tune the work over time is one of bcrypt’s most valuable features.

Hash

The hash is the output that is stored and compared at sign-in. Because bcrypt is a one-way function, the original password cannot be recovered from the hash by reversing the calculation. An attacker who steals a database of bcrypt hashes still has to guess passwords one by one, applying the salt and cost factor each time. That guessing is slow by design, and it is much slower than guessing against a fast hash.

How to Store Passwords With Bcrypt

The following steps describe the correct pattern for a developer building a login system. They are a high-level guide, not a code tutorial, and they assume the use of a well-tested library for the language in use.

  1. When a user creates a password, generate a fresh random salt. The bcrypt library usually handles salt generation automatically. Do not reuse a salt, and do not use a fixed salt for all users.
  2. Hash the password with bcrypt and a sensible cost factor. Choose a cost factor that makes a single hash take a noticeable but acceptable amount of time, commonly in the range of a few hundred milliseconds on the server. Do not choose the lowest setting just to make sign-in faster.
  3. Store the full bcrypt output, including salt and cost factor. The library’s output string contains everything needed to verify the password later. Store that string in the password field. Never store the plain password alongside it.
  4. When a user signs in, hash what they typed with the stored parameters and compare. Use the library’s verification function, which extracts the salt and cost factor from the stored hash and applies them to the entered password. Compare the result in a way that does not leak timing information, using the library’s built-in compare function.
  5. Upgrade hashes over time. If you raise the cost factor later, rehash passwords when users sign in, because that is when the plain password is briefly available. Do not wait for a breach to improve hashing. Plan upgrades as part of normal maintenance.

Worked Example: What Happens After a Database Leak

Imagine two websites each suffer a database leak. The first site stored passwords as fast hashes with no salt. The second site stored passwords as bcrypt hashes with a unique salt and a sensible cost factor.

For the first site, the attacker can start guessing immediately and very quickly. Common passwords fall in the first minutes, because the attacker can try huge numbers of guesses per second and can reuse precomputed tables. Passwords that appear in leaked lists are identified almost at once. The attacker does not need to work hard for each account, because one fast calculation can be checked against many hashes at once.

For the second site, the attacker’s task is very different. Each password has its own salt, so precomputed tables are useless. Each guess requires a slow bcrypt calculation. Trying the same list of common passwords now takes far longer, because the cost factor multiplies the work for every single guess. Strong, unique passwords in the second database may remain out of reach entirely, even after a long attack. The leak is still serious, and affected users should still change their passwords, but bcrypt has bought time and has kept many accounts safe.

This example shows why the choice of hash matters. Both sites stored hashes rather than plain text, but only the second site used a hash designed for passwords. A fast hash with no salt gives an attacker speed and scale. Bcrypt with a salt and a cost factor takes both advantages away.

Bcrypt Versus Fast Hashes Such as MD5 and SHA-256

MD5 and SHA-256 are well-known hash functions, but they were designed for different jobs, such as checking whether a file has changed. They are fast by design, and that speed is exactly what makes them unsuitable for password storage. An attacker with modern hardware can try very large numbers of MD5 or SHA-256 guesses in a short time. Even a password that would resist guessing for a long time against bcrypt can fall much sooner against a fast hash.

MD5 has additional problems. It is considered broken for many purposes because collisions have been demonstrated, and it should not be used for password storage at all. SHA-256 is a stronger general-purpose hash than MD5, but it is still far too fast for passwords when used on its own. Adding a salt to SHA-256 helps against precomputed tables, but it does not fix the speed problem.

Bcrypt, by contrast, is slow by design, includes a salt automatically, and lets developers raise the cost factor as hardware improves. Other modern password hashing functions, such as scrypt and Argon2, share the same philosophy and are also suitable choices. The key principle is the same in every case: passwords need a slow, salted, tunable hash designed for password storage, not a fast general-purpose hash.

Common Mistakes to Avoid

Never store plain passwords. Never store passwords encrypted with a reversible method when a hash would do, because encryption can be reversed if the key leaks. Never use bcrypt output as encryption. A hash is not an encryption key, and bcrypt output is not meant to hide data that you later need to read back. Hashing and encryption solve different problems, and they should not be confused.

Do not try to invent your own password hashing scheme, and do not combine hashes in improvised ways in the hope of making them stronger. Improvised schemes often introduce flaws that are hard to spot. Use a standard, well-tested library, keep it updated, and follow its documentation. Do not lower the cost factor to speed up sign-in, and do not reuse salts. Do not log passwords, include them in error messages, or store them in backups alongside the hashes.

Limitations

Bcrypt does not make a weak password strong. If users choose common passwords, those passwords can still be guessed, even against bcrypt, because guessing tools try common passwords first. Bcrypt slows guessing, but it does not remove the need for strong, unique passwords and for two-factor authentication. Bcrypt also does not protect against phishing, malware, or an attacker who already controls the server and can observe passwords as they are typed.

Bcrypt has a maximum input length in many implementations, and very long passwords may be truncated if the developer does not handle that case. Developers should check their library’s documentation and consider pre-hashing or length limits as advised by that library. Finally, bcrypt protects passwords that are stored correctly. It cannot help if passwords are also stored elsewhere in plain text, such as in logs, session data, or support tickets.

Frequently Asked Questions

Is bcrypt encryption?

No. Bcrypt is a one-way hash, not encryption. Encryption is reversible with a key. Hashing is designed to be impractical to reverse. You use hashing to verify a password without storing it, and encryption to protect data that you need to read back later.

Why does slowness help?

Slowness barely affects a legitimate sign-in, which happens once, but it greatly slows an attacker who must try many guesses. A cost factor that adds a fraction of a second per guess can turn a fast attack into an impractical one, especially when combined with a unique salt for each password.

Should I still use bcrypt for new projects?

Bcrypt remains a solid, widely supported choice for password storage. Newer options such as Argon2 are also suitable and may offer advantages on modern hardware. Either is far better than a fast hash. Choose a well-tested library, set a sensible cost factor, and keep the library updated.

What should users do if a site stored passwords badly?

Change the password for that site, and change it anywhere else you used the same password or a close variation. Turn on two-factor authentication. Treat the old password as exposed, even if the site says the leak was limited. A slow hash buys time, but a leak should always be treated as serious.

Conclusion

Passwords need slow hashing because attackers guess quickly. Bcrypt provides that slowness through a salt, a tunable cost factor, and a one-way hash designed for password storage. Used correctly, it turns a database leak from an instant disaster into a slow, difficult attack that protects many accounts. It is not a substitute for strong passwords or two-factor authentication, but it is an essential layer of defence for any site that stores passwords.