BCrypt variants
$2$
BCrypt was designed by the OpenBSD people. It was designed to hash passwords for storage in the OpenBSD password file. Hashed passwords are stored with a prefix to identify the algorithm used. BCrypt got the prefix $2$
.
This is in contrast to the other algorithm prefixes:
$1$
: MD5
$3$
: NTHASH
$5$
: SHA-256
$6$
: SHA-512
$7$
: scrypt
$2a$
The original BCrypt specification did not define how to handle non-ASCII characters, or how to handle a null terminator. The specification was revised to specify that when hashing strings:
- the string must be UTF-8 encoded
- the null terminator must be included
$2x$, $2y$ (June 2011)
A bug was discovered in crypt_blowfishπ, a PHP implementation of BCrypt. It was mis-handling characters with the 8th bit set.
They suggested that system administrators update their existing password database, replacing $2a$
with $2x$
, to indicate that those hashes are bad (and need to use the old broken algorithm). They also suggested the idea of having crypt_blowfish emit $2y$
for hashes generated by the fixed algorithm. Nobody else, including canonical OpenBSD, adopted the idea of 2x
/2y
. This version marker was was limited to crypt_blowfishπ.
The versions $2x$ and $2y$ are not "better" or "stronger" than $2a$. They are remnants of one particular buggy implementation of BCrypt.
$2b$ (February 2014)
A bug was discovered in the OpenBSD implementation of BCrypt. They were storing the length of their strings in an unsigned char
. If a password was longer than 255 characters, it would overflow and wrap at 255.
BCrypt was created for OpenBSD. When they have a bug in their library, they decided its ok to bump the version. This means that everyone else needs to follow suit if you want to remain current to "their" specification.
The version $2b$ is not "better" or "stronger" than $2a$. It is a remnant of one particular buggy implementation of BCrypt. But since BCrypt canonically belongs to OpenBSD, they get to change the version marker to whatever they want.
There is no difference between 2a, 2x, 2y, and 2b. If you wrote your implementation correctly, they all output the same result.
And if you were doing the right thing from the beginning (storing strings in utf8 and also hashing the null terminator) then: there is no difference between 2, 2a, 2x, 2y, and 2b. If you wrote your implementation correctly, they all output the same result.
The only people who need to care about 2x and 2y are those you may have been using crypt_blowfish. And the only people who need to care about 2b are those who may have been running OpenBSD.
All other correct implementations are identical and correct.
you will want to check against the $2a$ hash if the $2x$ check fails
, and then update to$2y$
. Do the mean is, sometimes passwords hashed with$2a$
inPHP 5.3.7-
will cannot verify with$2x$
inPHP 5.3.7+
? β Including$2a$
onPHP 5.3.7-
and want update the PHP to5.3.7+
we must after upgrade verify old passwords with$2x$
. So, only usage of$2x$
is just the same. If someone think i have realized mistake please aware me. Thanks β Including