bcrypt

Field: Security · Also called: BCrypt, bcrypt hash, Blowfish crypt, $2b$

bcrypt is a password hashing function, published by Niels Provos and David Mazières in 1999, that is built on an intentionally expensive Blowfish key schedule, uses a 128-bit salt for each password, and takes a cost factor that sets how much work each hash requires.

bcrypt is one of the password hashing functions in common use, alongside Argon2, scrypt, and PBKDF2. It was designed for storing passwords, not as a general-purpose hash function, and it is deliberately slow.

How it works

bcrypt is built on a variant of the Blowfish block cipher that Provos and Mazières called eksblowfish, for “expensive key schedule Blowfish.” Setting up its key schedule mixes in the password and the salt for 2cost iterations. The 192-bit value OrpheanBeholderScryDoubt is then encrypted 64 times with that key schedule. The output is the cost and the 128-bit salt, followed by the result of the encryption.

Because the cost is an exponent, raising it by one doubles the work for the server and for anyone trying to guess passwords from a stolen copy of the hashes. That adjustable cost was the point of the 1999 paper, titled “A Future-Adaptable Password Scheme.”

Reading a bcrypt hash

A bcrypt hash is stored as a single 60-character string that carries everything needed to verify a password later:

$2b$12$GjfcaMzwIz9gUCXzk69n2Oc1rdA/JbDoEPVtHdKZ/7yp/m.cg2Dy6
  • 2b is the version, explained in History below.
  • 12 is the cost, the base-2 logarithm of the iteration count. OpenBSD and PHP accept a cost from 04 to 31.
  • The next 22 characters are the salt, and the remaining 31 characters are the hash. Both use bcrypt’s own Base64 alphabet (./0-9A-Za-z).

Since the salt and cost travel with the hash, an application can raise the cost for new passwords without touching existing records, then rehash each old record at that user’s next successful login; see Password hash upgrade.

The 72-byte input limit

Most implementations use only the first 72 bytes of the password. In the original OpenBSD implementation, anything after that is silently ignored, so two long passwords that share their first 72 bytes produce the same hash. The 1999 paper itself describes keys of up to 56 bytes, including a terminating zero byte; the 72-byte limit comes from the implementations. Bytes are not characters: a password of non-ASCII characters in UTF-8 reaches the limit in fewer than 72 characters.

OWASP’s Password Storage Cheat Sheet recommends enforcing a maximum password length of 72 bytes. It also warns that hashing the password first and passing the result to bcrypt, a common workaround, is “dangerous” because of null bytes in the hash output and because of password shucking, and it gives a peppered HMAC construction for systems that must do so. Some libraries now refuse longer input instead of truncating it; pyca/bcrypt, the Python library, raises an error.

Current guidance

OWASP’s cheat sheet lists Argon2id first and scrypt second, and says bcrypt “should only be used for password storage in legacy systems where Argon2 and scrypt are not available,” with a cost of at least 10. Unlike Argon2 (RFC 9106) and scrypt (RFC 7914), bcrypt is not memory-hard, so it can be computed with little memory per guess, which makes large-scale parallel cracking on specialized hardware cheaper. Where FIPS-140 compliance is required, OWASP recommends PBKDF2.

History

Provos and Mazières presented bcrypt at the 1999 USENIX Annual Technical Conference. It was implemented in OpenBSD.

In June 2011, Openwall released crypt_blowfish 1.1 to fix CVE-2011-2483: most passwords containing characters with the eighth bit set had been hashed incorrectly, and in some cases one to three characters before them were ignored. Hashes from the incorrect implementation could be verified under a $2x$ prefix during a transition period, while new hashes used the usual $2a$. PHP’s manual now describes $2x$ hashes as potentially weak and says new hashes should use $2y$.

In February 2014, OpenBSD fixed a bug in its own implementation, which stored the password length in an 8-bit integer, so the length wrapped around at 256 bytes. The commit added a $2b$ version that caps input at 72 bytes; OpenBSD continued generating $2a$ hashes for a time.

Sources

See also

Go deeper

Articles