Where 2x prefix are used in BCrypt?
Asked Answered
I

1

33

The question is the same title, Where $2x$ is used in BCrypt?

The following scenario is right?

We have a set of passwords that hashed with $2a$ prefix already, when the Server PHP version was earlier 5.3.7. Now we upgraded the PHP to 5.3.7+, now we must firstly verify previous passwords with $2x$ algorithm then rehash the password with $2y$ prefix. That's right?

Including answered 31/3, 2013 at 18:53 Comment(2)
Can found a good answer in this weblog. but i didn't understand what say in this sentence: Now, this code assumes that you spotted the issue before updating the server; if you have had new passwords created since the upgrade, 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$ in PHP 5.3.7- will cannot verify with $2x$ in PHP 5.3.7+? – Including
Another answer:CRYPT_BLOWFISH security fix details Result: As far as i understand when we have a set of passwords hashed with $2a$ on PHP 5.3.7- and want update the PHP to 5.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
C
119

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.

Cosignatory answered 25/3, 2016 at 17:54 Comment(6)
Something that just doesn't make sense to me is that bcrypt seems to truncate input to 72 characters (or bytes?) by design, so the 255-char wraparound shouldn't have occured in the first place... – Shaeshaef
It truncates to 72 bytes. Nominally you supply those bytes as the UTF-8 encoding of the original text, and you include the null terminator. But in the end, the nominal-implementation cuts off after 72 bytes; cutting off the null terminator, even cutting it off mid-utf8 multi-byte character. But they don't artifically limit the number of characters to 71. Technically you can have one "character" take more than 72 bytes (e.g. "MΜ€ΜΜ‚ΜƒΜ„Μ…Μ†Μ‡Μ‰ΜŠΜ‹ΜŒΜΜŽΜΜΜ‘Μ’Μ“Μ”Μ•Μ–Μ—Μ˜Μ™ΜšΜ›ΜœΜΜžΜŸΜ Μ‘Μ’" is 1 character, 74 bytes. πŸ’© is one character, but 4 bytes). – Cosignatory
There's also the reality of how they are actually storing a string. In decent languages, a string in internally length-prefixed and null terminated. Lesser languages have no actual "string" type, so they fake it as a pointer to a CHAR, and can also carry a length along with it. And in this case they got their hacky string-type wrong, using UInt8 rather than UInt32 as a length prefix. It would all have been solved if C and C++ would finally do the right thing and add a "string" type. But at this point the language maintaniners refuse to add string and array out of spite. – Cosignatory
Nit-pick: Bcrypt landed in 1997 in OpenBSD 2.1. sha256crypt and sha512crypt by Ulrich Drepper landed in glibc 2.7 in 2007, a full decade later. $2$ was indeed chosen to follow md5crypt $1$. However, Urlich Drepper chose $5$ and $6$ as $3$ was chosen for NTHASH. I don't know why he skipped $4$. – Bcd
@AaronToponce Your history is useful and interesting, but i'm don't know what nit you're picking. Were you referring to $4$ missing from my example list of prefixes? – Cosignatory
@IanBoyd Your phrasing makes it appear as though bcrypt chose $2$, because $1$, $5$, and $6$ were already in practice, where $5$ and $6$ didn't exist. "BCrypt got the prefix $2$. This was in contrast to the other algorithm prefixes." – Bcd

© 2022 - 2024 β€” McMap. All rights reserved.