Hi all,
I'd like to open the discussion on a new password hashing algorithm that
I've been working on, named bcrypt-wrap.
RFC link: https://wiki.php.net/rfc/password_bcrypt_wrap
Pull request: https://github.com/php/php-src/pull/25040 (just pushed it, CI
still running)
P.S. Thanks to Sjoerd for honoring my request to delay his bcrypt-sha256
proposal while I finished this.
Cheers,
Andrey.
Hi all,
I'd like to open the discussion on a new password hashing algorithm that I've been working on, named bcrypt-wrap.
RFC link: https://wiki.php.net/rfc/password_bcrypt_wrap
Pull request: https://github.com/php/php-src/pull/25040 (just pushed it, CI still running)P.S. Thanks to Sjoerd for honoring my request to delay his bcrypt-sha256 proposal while I finished this.
Cheers,
Andrey.
Hi Andrey,
I'm rather against it. Your proposed implementation decreases security
of bcrypt implementation for small and dubious gains. The input space
is decreased from 2^576 to 2^432, which is a magnitude of 2^144. Sure,
these are astronomical values, but it's a significant decrease
nonetheless.
Additionally, your implementation suffers from hash shucking. OWASP
explicitly warns about doing it the way you are doing it:
Just using pure SHA-512, ( i.e. bcrypt(base64(sha512($password))), $salt, $cost)) is a dangerous practice and is as secure as just using pure SHA-512.
https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
You mention HMAC, but it's a bit vague and looking at the
implementation, I believe you use the public salt as a secret key.
This may obfuscate the hash, but as I understand it, it does not make
pre-hashing safe. In fact the blog which I assume you have looked at
before (https://soatok.blog/2024/11/27/beyond-bcrypt/) describes the
problems in detail:
You can avoid hash shucking by using HMAC with a static key–either universal for all deployments of your software, or unique per application.
It doesn’t really matter which you choose; all you really need from it is domain separation from naked hashes.
So what do we gain instead? Your RFC does not clearly state the
benefits we gain at the cost of reduced security.
Regards,
Kamil Tekiela
Hi Kamil,
I'm rather against it. Your proposed implementation decreases security
of bcrypt implementation for small and dubious gains. The input space
is decreased from 2^576 to 2^432, which is a magnitude of 2^144. Sure,
these are astronomical values, but it's a significant decrease
nonetheless.
Sorry, but this is complete nonsense. A prehash doesn't reduce Bcrypt's
security or input space, and the "dubious gains" are masking all of
Bcrypt's limitations on inputs.
Additionally, your implementation suffers from hash shucking. OWASP
explicitly warns about doing it the way you are doing it:
Just using pure SHA-512, ( i.e. bcrypt(base64(sha512($password))),
$salt, $cost)) is a dangerous practice and is as secure as just using pure
SHA-512.https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
That's not how I'm doing it. Not even close.
You mention HMAC, but it's a bit vague and looking at the
implementation, I believe you use the public salt as a secret key.
This may obfuscate the hash, but as I understand it, it does not make
pre-hashing safe. In fact the blog which I assume you have looked at
before (https://soatok.blog/2024/11/27/beyond-bcrypt/) describes the
problems in detail:You can avoid hash shucking by using HMAC with a static key–either
universal for all deployments of your software, or unique per application.It doesn’t really matter which you choose; all you really need from it is
domain separation from naked hashes.
I'm happy to correct vagueness, especially if you can point to the unclear
piece of text. However, you are wrong on multiple counts here, and the
answer as to why is in those exact last words in the quote: domain
separation from naked hashes.
Not only is there domain separation from naked hashes, there's domain
separation between the Bcrypt and prehash salts (and even further than
that).
And while I have indeed read Soatok's blog, the insinuation that it's the
basis of my work is both rude and false. I'd be more than familiar with
password shucking with or without it, which is why I can tell you what he
meant there by suggesting a static key: even a static key is good enough,
not only a static key.
The salt being used that way adds more strength (which some would call
overkill), not less. It being public has no effect on the purpose it serves
either.
So what do we gain instead? Your RFC does not clearly state the
benefits we gain at the cost of reduced security.
Perhaps it was foolish of me to think that listing Bcrypt's well-known
issues in the very first sentence of the RFC introduction is enough to
suggest that they'd be fixed. Maybe I could be more explicit about it, and
maybe you could not so aggressively strawman too. Just to be crystal clear:
there is no reduced security.
Cheers,
Andrey.