Why bcrypt is intentionally slow
Cover photo by Markus Spiske on Unsplash
Bcrypt is slow because its creators wanted to make brute force attacks prohibitively expensive. That is it. That is the whole point of its existence.
The naive way to hash passwords
When I first started building auth systems, I thought MD5 or SHA-256 were the standard. They are fast. Really fast. Let’s look at what happens if we use a simple SHA-256 hash.
const crypto = require('crypto');const hash = crypto.createHash('sha256').update('myPassword123').digest('hex');This is a terrible idea for passwords. If someone steals your database, they can compute millions of these hashes per second on a decent GPU. If you store your passwords using a raw, fast algorithm, you are basically handing your users’ credentials to hackers on a silver platter. It takes them milliseconds to crack common passwords.
Enter bcrypt
Bcrypt solves this by being intentionally difficult to compute. It uses a cost factor to control how long the hashing process takes. As hardware gets faster, you increase the cost factor to keep the computation time stable (or as slow as you need it to be).
Here is how you would use it in a Node.js project:
const bcrypt = require('bcrypt');const saltRounds = 12;const password = 'myPassword123';
// This will take a noticeable fraction of a secondbcrypt.hash(password, saltRounds, (err, hash) => { // Store the hash});Why the delay matters
If it takes 200 milliseconds to hash a single password, that is annoying for your server, but it is catastrophic for a hacker. A hacker with a powerful rig might be able to compute billions of SHA-256 hashes in a short window. With bcrypt, that same hardware is slowed down to a crawl. The math behind the algorithm requires constant memory and computation that isn’t easily parallelized on cheap graphics hardware.
“But doesn’t this slow down my login endpoint?” Yes. It definitely does. That is a fair concern for high traffic apps. You have to handle this by offloading the hashing to a background worker or ensuring your server infrastructure handles the load. If your app is getting hit with thousands of concurrent logins, you’re going to need more than just one cheap VPS (I’ve definitely run into scaling issues here before).
The trade-off
I admit, there are scenarios where bcrypt might be overkill or the wrong tool. If you are hashing millions of data points that aren’t passwords, or if you are in a weird edge case where CPU cycles are literally more expensive than the security risk, maybe you look at Argon2 or something else. Actually, Argon2 is arguably the modern standard, but bcrypt is still widely respected and vastly better than the fast cryptographic hashes people often accidentally pick.
Don’t try to roll your own security. Don’t use fast algorithms for passwords because you want a snappy login page. Your user’s security is worth an extra 200ms of latency every single time. It is a small price to pay for sanity.