Bcrypt Generator

An online bcrypt generator: make a hash, check a password against one or take a hash apart. Hashed in your browser: nothing is sent.

11 libraries checked · hashed in your browser

ForPick the libraries that will check the hash: the prefix follows.

  • 10OWASP's minimum · Node, bcryptjs, Go, Spring
  • 11.NET
  • 12PHP 8.4, Python, Ruby, Rust

Timing bcrypt on this device…

Prefix

Auto writes $2b$, OpenBSD's prefix. Pick your languages to match what they read.

Hashed in your browser: no password or hash is sent.

The hash

Your hash appears here.

Bcrypt Generator: a password hashed at cost 10 for PHP and Node, the hash taken apart and the libraries that read itBcrypt Generator: a password hashed at cost 10 for PHP and Node, the hash taken apart and the libraries that read itPick your languagesThe prefix follows what every library you pick reads: PHP and Node's bcrypt share only $2a$ and $2b$.The 72-byte cutbcrypt reads the first 72 bytes. Anything past them is struck through as you type.Cost, timed hereThis device times the cost first. Each step doubles the work, and the server pays it on every check.The hash, taken apartPrefix, cost, salt and digest, each labelled.Who reads this prefix11 libraries, each with its verdict on this hash and a link to the source behind it.
A hash for PHP and Node: the page picks a prefix both read, takes the hash apart and shows which of 11 libraries read it.

What is bcrypt?

bcrypt is a password hash built to be slow on purpose. It mixes the password with a random 128-bit salt through 2^cost rounds of the Blowfish key schedule, so raising the cost by one doubles the work for anyone guessing.

A bcrypt hash carries everything needed to check it: the version after $2, the cost, then 22 characters of salt and 31 of hash in bcrypt's own base64. That's why two hashes of the same password look different, and why a server needs only the stored line and the password to check it. The Decode tab is a bcrypt decoder: paste any hash to see these parts.

It was published in 1999 by Niels Provos and David Mazières, at USENIX, as "A Future-Adaptable Password Scheme": the cost lets the work grow as computers get faster.

bcrypt("example-passphrase", cost 10)

$2b$version10$cost · 2^10 = 1,024 roundsF2BfOoKCXaWlgMjIouvrxesalt (16 bytes)0.WbSz4KRwXIPeT5AMjqGn7b1Vlf07Khash

A bcrypt hash of a made-up password, taken apart.

Sources: usenix.org · man.openbsd.org

$2a$, $2b$ or $2y$: which bcrypt prefix should I use?

They're the same hash. What differs is which labels a library accepts: Node.js's bcrypt package and OpenBSD read only $2a$ and $2b$, Apache for Windows never checks $2b$, and $2a$ is read by every library below. Pick the readers above the tool and it picks the prefix.

$2a$ is the original label. $2b$ marks OpenBSD's 2014 fix for passwords of 256 characters or more, and $2y$ marks crypt_blowfish's correct implementation, which PHP writes. $2x$ is different: it means a hash made with an old bug, and libraries that accept it may not reproduce that bug.

$2a$$2b$$2y$$2x$writes
PHPreads itreads itreads itreads it$2y$
Node.js bcryptreads itreads itdoesn't read itdoesn't read it$2b$
bcryptjsreads itreads itreads itdoesn't read it$2b$
Python bcryptreads itreads itreads itaccepts the label only$2b$
Go x/cryptoreads itreads itreads itreads it$2a$
Java Springreads itreads itreads itdoesn't read it$2a$
.NET BCrypt.Netreads itreads itreads itreads it$2a$
Ruby bcryptreads itreads itreads itreads it$2a$
Rust bcryptreads itreads itreads itaccepts the label only$2b$
OpenBSDreads itreads itdoesn't read itdoesn't read it$2b$
Apache (htpasswd)reads itaccepts the label onlyreads itreads it$2y$
Apache on Windowsreads itdoesn't read itreads itreads it$2y$

✓ reads it– accepts the label only✗ doesn't read it

Which prefixes each library accepts when it checks a hash, from its own documentation or code.

Sources: php/php-src on GitHub · kelektiv/node.bcrypt.js on GitHub · dcodeIO/bcrypt.js on GitHub · pyca/bcrypt on GitHub · golang/crypto on GitHub · spring-projects/spring-security on GitHub · BcryptNet/bcrypt.net on GitHub · bcrypt-ruby/bcrypt-ruby on GitHub · Keats/rust-bcrypt on GitHub · openbsd/src on GitHub · apache/apr-util on GitHub · besser82/libxcrypt on GitHub · openbsd.org · openwall.com

What is a good bcrypt cost?

10 is OWASP's minimum and 12 is a common default today: PHP since 8.4, Python, Ruby and Rust all use 12. Each step doubles the time, both for an attacker and for your server on every login, so pick the highest your login can afford.

The tool times your cost on this device before it hashes, and anything from 13 up runs with an estimate and a Cancel button, so a cost of 20 can't freeze the page.

  1. 41/64×
  2. 51/32×
  3. 61/16×
  4. 71/8×
  5. 81/4×
  6. 91/2×
  7. 101×OWASP's minimum · Node.js bcrypt · bcryptjs · Go x/crypto · Java Spring
  8. 112×.NET BCrypt.Net
  9. 124×PHP · Python bcrypt · Ruby bcrypt · Rust bcrypt
  10. 138×
  11. 1416×
  12. 1532×
  13. 1664×
The work at each cost relative to 10, with each library's default.

Sources: cheatsheetseries.owasp.org · php.net · php/php-src on GitHub · kelektiv/node.bcrypt.js on GitHub · dcodeIO/bcrypt.js on GitHub · pyca/bcrypt on GitHub · golang/crypto on GitHub · spring-projects/spring-security on GitHub · BcryptNet/bcrypt.net on GitHub · bcrypt-ruby/bcrypt-ruby on GitHub · Keats/rust-bcrypt on GitHub · man.openbsd.org · openbsd/src on GitHub

What is bcrypt's 72-byte limit?

bcrypt reads only the first 72 bytes of a password. Most libraries ignore the rest without a word, so two long passwords that share their first 72 bytes match each other. Some now refuse instead: Python's bcrypt since 5.0, and Go and Spring when they hash.

Bytes, not characters: in UTF-8 an accented letter takes two bytes and an emoji four, so a 30-character passphrase in another script can pass the limit. The Hash tab counts the bytes as you type and strikes out what would be ignored.

Hashing the password first with a fast hash to get round the limit has its own traps: OWASP warns about NUL bytes and "password shucking", and prescribes an HMAC with a secret pepper if you must.

91 characters · 93 bytes in UTF-8

Pässphrase für die Wartung: correct horse battery staple, the harbour at six in the morning

  • ignores the restPHP, Node.js bcrypt, bcryptjs, .NET BCrypt.Net, Ruby bcrypt, Rust bcrypt, OpenBSD
  • refuses to hash (checking still accepts)Go x/crypto, Java Spring
  • refuses to hash and to checkPython bcrypt
A made-up passphrase with the 72-byte cut, and what each library does past it.

Sources: openbsd/src on GitHub · php.net · php/php-src on GitHub · kelektiv/node.bcrypt.js on GitHub · dcodeIO/bcrypt.js on GitHub · pyca/bcrypt on GitHub · golang/crypto on GitHub · spring-projects/spring-security on GitHub · BcryptNet/bcrypt.net on GitHub · bcrypt-ruby/bcrypt-ruby on GitHub · Keats/rust-bcrypt on GitHub · man.openbsd.org · cheatsheetseries.owasp.org

How do I hash and check bcrypt in my language?

Every mainstream language has a bcrypt library with two calls: one that hashes with a fresh salt, one that checks a password against a stored hash. Never compare hashes as strings: the salt makes each hash different.

PHP
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$ok = password_verify($password, $hash);
Node.js (bcrypt)
const hash = await bcrypt.hash(password, 12);
const ok = await bcrypt.compare(password, hash);
Python (bcrypt)
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
ok = bcrypt.checkpw(password.encode(), hashed)
Go (x/crypto/bcrypt)
hash, err := bcrypt.GenerateFromPassword([]byte(password), 12)
err = bcrypt.CompareHashAndPassword(hash, []byte(password)) // nil = match
Java (Spring Security)
var encoder = new BCryptPasswordEncoder(12);
String hash = encoder.encode(password);
boolean ok = encoder.matches(password, hash);
C# (BCrypt.Net-Next)
string hash = BCrypt.Net.BCrypt.HashPassword(password, 12);
bool ok = BCrypt.Net.BCrypt.Verify(password, hash);
Ruby (bcrypt)
hash = BCrypt::Password.create(password)  # cost 12 by default
ok = BCrypt::Password.new(hash) == password
Rust (bcrypt)
let hash = bcrypt::hash(password, 12)?;
let ok = bcrypt::verify(password, &hash)?;
Hash, then check, with each library's own calls.

Sources: php.net · kelektiv/node.bcrypt.js on GitHub · pyca/bcrypt on GitHub · golang/crypto on GitHub · docs.spring.io · BcryptNet/bcrypt.net on GitHub · bcrypt-ruby/bcrypt-ruby on GitHub · Keats/rust-bcrypt on GitHub

Argon2 vs bcrypt: which should I use?

For a new system, OWASP recommends Argon2id first, then scrypt, with bcrypt for legacy systems at a cost of 10 or more and PBKDF2 where FIPS-140 compliance is required. Argon2 won the Password Hashing Competition in 2015. bcrypt is still sound where it already runs, within its 72-byte limit.

  1. Argon2idfirst choice
  2. scryptwhere Argon2id isn't available
  3. bcryptlegacy systems, cost 10 or more, 72-byte limit
  4. PBKDF2where FIPS-140 compliance is required
OWASP's order of password hashes.

Sources: cheatsheetseries.owasp.org · password-hashing.net · OWASP/CheatSheetSeries on GitHub

Can bcrypt be decrypted?

No. There's no bcrypt decrypt: bcrypt is one-way, so there's nothing to decrypt. Someone holding the hash can only guess passwords and run bcrypt on each guess, which is what the cost slows down. The Check tab answers the question that's left: does this password match this hash?

One graphics card manages about 305,000 bcrypt guesses a second at cost 5, and every step up halves that: about 9,500 at cost 10 and 600 at cost 14.

  • bcrypt, cost 5304,800 guesses a second
  • bcrypt, cost 109,525 guesses a second
  • bcrypt, cost 122,381 guesses a second
  • bcrypt, cost 14595 guesses a second
Guesses per second on one RTX 5090 (hashcat's own benchmark at cost 5, halved for each step).

Sources: gist.github.com · openbsd/src on GitHub

bcrypt FAQ

Is it safe to make a bcrypt hash online here?

This page hashes in a worker inside your browser: the text you type and the hash it makes never leave it, and nothing is stored or put in the address bar. You can see it in your browser's developer tools, where the Network tab shows no request while you hash, check or decode. Treat the hash like the password it protects: anyone who has it can try guesses offline.

What is a good bcrypt cost?

OWASP's minimum is 10, and it says to go as high as your server allows. Library defaults differ: 10 in Node's bcrypt, bcryptjs, Go and Spring, 11 in .NET, and 12 in PHP 8.4, Python, Ruby and Rust. Each step doubles the work and the server pays it on every login, so time it first: this page measures the cost on your device before it runs.

Why does my $2y$ hash fail in Node.js?

Node's bcrypt package checks only $2a$ and $2b$ hashes, so compare() returns false for the $2y$ hashes that PHP and htpasswd write, even with the right password. The hash itself is the same under all three prefixes, so changing $2y$ to $2b$ makes it match. bcryptjs, the pure JavaScript package, reads $2y$ as it is.

$2a$ vs $2b$ vs $2y$: what's the difference?

All three mark the same algorithm today. $2a$ is the original prefix; OpenBSD added $2b$ in 2014 to fix a length bug in its own code, and crypt_blowfish writes $2y$ for correctly computed hashes, which behave exactly like $2b$. What differs is who accepts which: OpenBSD and Node's bcrypt refuse $2y$, Apache for Windows refuses $2b$, and all of them read $2a$.

Why are two hashes of the same password different?

Each hash gets a new random salt of 16 bytes, the 22 characters after the cost. The salt is stored in the hash, so the checking code reads it back and hashes the password again with it. Two users with the same password end up with different hashes, which is why you check a password against a hash rather than compare two hashes.

What is bcrypt's 72-byte limit?

bcrypt uses at most the first 72 bytes of a password; the rest never reaches the hash. Most libraries cut it silently, so two long passwords that start the same match each other. Some refuse instead: Go and Spring won't hash longer input, and Python's bcrypt 5.0 refuses it both ways. It counts bytes, not characters, and many emoji take four.

Can bcrypt be decrypted?

No. bcrypt is a one-way function, so there is nothing to decrypt. A hash can only be checked against a guess, which is what the Check tab does, or attacked by trying passwords at 2^cost rounds each. The Decode tab takes a hash apart into its prefix, cost, salt and digest, but none of those parts contains the password.

Should I use Argon2 instead of bcrypt?

For new systems, OWASP lists Argon2id first, then scrypt, and keeps bcrypt for legacy systems where those aren't available, with a cost of at least 10. Argon2 won the Password Hashing Competition in July 2015. If your framework already uses bcrypt, keep the cost at 10 or more and the input within 72 bytes.

Missing something?Suggest a feature or a new tool