Nimble Toolbox

Generate and check bcrypt hashes

Type a password to get its bcrypt hash, or switch to Check and paste a hash to see whether a password matches it. The work happens in this tab, so the password is never sent anywhere.

Result
Variant
—
Cost
—
Salt?
—
Hash
—

How to use it#

  1. Choose Hash to make a new hash, or Check to test a password against an existing hash.
  2. Type the password. To hash, pick a cost; the hash appears once you stop typing, with its variant, cost, salt, and hash listed beneath it.
  3. To check, paste the bcrypt hash as well, and the result says whether they match.
  4. Copy the hash, or press New salt for a different hash of the same password.

Why bcrypt, and not a plain hash#

A password database gets stolen sooner or later, and what matters then is how long it takes to turn the stored values back into passwords. A fast hash such as SHA-256 is built to be computed billions of times a second, so an attacker with a graphics card can try every common password against every account in an afternoon. The hash generator is the right tool for checksums for exactly that reason, and the wrong one for passwords.

bcrypt is slow on purpose and salted on purpose. Every hash carries its own random salt, so two people with the same password get different hashes and one guess cannot be tested against the whole table at once. And its cost setting decides how much work each guess takes, which can be raised as hardware gets faster.

Newer designs exist. Argon2id, and scrypt before it, also demand a lot of memory, which makes them harder to attack with specialised hardware. bcrypt remains a sound choice that every language and framework supports, and a site already using it has no urgent reason to move.

Reading a bcrypt hash#

A bcrypt hash is 60 characters in four parts. $2b$12$R9h/cIPz0gi.URNNX3kh2O and then 31 more characters reads as: version 2b, cost 12, then 22 characters of salt, then the hash itself. Everything needed to check a password is in the string, which is why a login system can store this one value and nothing else. A hash made here is shown split into those parts, and one pasted into Check shows its variant, cost, and salt.

The version letters come from history. $2a$ is the form most older systems write, $2y$ is how PHP marks hashes made after it fixed a bug in its own implementation, and $2b$ is the mark OpenBSD adopted for a separate fix to how very long passwords were counted. For a password in plain ASCII all three give the same result, and this page reads any of them. Hashes made here are $2b$.

An Apache htpasswd file holds one user a line: the name, a colon, and the hash. To test a password against an entry, paste the part after the colon into Check. htpasswd writes $2y$, and a $2b$ hash made here can be changed to $2y$ for a new entry, since the two variants compute the same hash.

Choosing the cost#

The cost is a power of two: cost 10 runs the expensive setup 1,024 times, cost 12 runs it 4,096 times, and each step up doubles the time. Pick the highest cost your login server can compute in about a quarter of a second, which for most servers today is 12, the default in several major web frameworks. Below 10 is too fast to slow an attacker much.

Libraries give the same number different names. It is rounds in Python's bcrypt and in Laravel, saltRounds in the examples for Node's bcrypt package, strength in Spring Security, and cost in PHP's password_hash. Some call it the work factor or log rounds. Whatever the name, a hash made at 12 here matches a hash made at 12 by any of them.

The time shown here is how long your browser took, running bcrypt in JavaScript, which is several times slower than a server running native code. Treat it as a comparison between costs rather than a prediction of your server.

Frequently asked questions#

Is it safe to type a real password here?

#

The password is hashed in this tab by your browser and never transmitted, so nothing is exposed by typing it. Still, a hash made on any web page is best used for testing. For production, hash passwords in your own application code, where the salt and the result never pass through a browser at all.

What cost should I use?

#

The highest your server can compute in roughly 250 milliseconds, which is usually 12. Each step up doubles the time for both you and an attacker, so 13 is twice as slow as 12. Costs above 16 are not offered for hashing, because in a browser they take many seconds each, but a hash of any cost from 4 to 31 can be checked.

Why is the hash different every time for the same password?

#

Each hash gets a new random salt, stored inside the hash itself. That is the point: the same password never produces the same stored value twice, so a stolen table cannot be attacked with a precomputed list. Checking still works, because the check reads the salt back out of the hash. So to test a password, compare it with the stored hash rather than hashing it again and comparing the strings. That is what bcrypt.compare in Node, checkpw in Python, and password_verify in PHP do, and what Check does here.

Do I need to store the salt separately?

#

No. bcrypt writes the salt into the hash, so the one 60 character string is all you store. In $2b$12$ followed by 53 characters, 2b is the variant, 12 is the cost, the next 22 characters are the salt, and the last 31 are the hash itself. Checking a password reads the variant, cost, and salt back out of that string, which is why this page can check a hash without being told the salt, and why a hash made here checks anywhere else that reads bcrypt.

Is there a maximum password length?

#

Yes. bcrypt uses only the first 72 bytes of a password and silently ignores the rest. Most passwords are nowhere near that, but a long passphrase or one made of emoji and accented letters, which take several bytes each, can pass it. The page warns when that happens.

Can a bcrypt hash be decrypted?

#

No. bcrypt is a one-way function, not encryption, so there is no key that turns a hash back into its password. The only way to recover one is to guess passwords and check each guess, which is exactly the work the cost setting makes expensive. A strong password, which the password generator can make, is what keeps guessing hopeless.

Does it check $2y$ hashes from PHP?

#

Yes. $2a$, $2b$, and $2y$ hashes are all checked, so a hash from PHP password_hash or from Laravel, which both write $2y$, can be verified here the same way password_verify would. $2x$ hashes, made by old PHP versions affected by a bug in how they handled some characters, cannot be checked reliably by any current bcrypt and are refused with an explanation.