Re: RFC proposal to deprecate crypt()
| From: | steve at tobtu dot com | Date: | Sun, 20 Feb 2022 11:44:04 +0000 |
| Subject: | Re: RFC proposal to deprecate crypt() | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-117074@lists.php.net to get a copy of this message | ||
> On 02/20/2022 1:10 AM Stanislav Malyshev <smalyshev@gmail.com> wrote:
>
>
> Hi!
>
> On 2/19/22 6:03 PM, steve@tobtu.com wrote:
> > crypt() should be deprecate because it can be used to create bad password hashes:
>
> I don't think it's a good reason for deprecating functions. A lot of
> functions, if used incorrectly, could produce bad results, it's not the
> reason to not use them correctly.
>
Sorry, I really meant to say it can *only* create bad password hashes... and bcrypt which
password_hash() is the preferred function to create a bcrypt hash.
crypt() should be deprecated, unless there's a reason to let users write:
$hash = crypt($password, "$2y$" . str_pad($cost, 2, "0", STR_PAD_LEFT) .
strtr(base64_encode(random_bytes(16)), '+', '.'));
// hi from 9 years ago https://www.php.net/manual/en/function.crypt.php#111086
(oof... ignore the minor errors and the update with random_bytes() because mcrypt was deprecated
then removed)
vs
$hash = password_hash($password, PASSWORD_BCRYPT);
Note the crypt() documentation: "password_hash() uses a strong hash, generates a strong salt,
and applies proper rounds automatically. password_hash() is a simple crypt() wrapper and
[password_verify() is] compatible with existing password hashes. Use of password_hash() is
encouraged." That is the exact reason why mcrypt was deprecated: hard to use correctly and most
uses of it were broken.
Also ~99% of implementations of crypt() that use sha256crypt and/or sha512crypt password hashing
algorithms are vulnerable to a long password DoS attack. Since they don't know they need to
limit the password length because the runtime is O(pwLen^2+pwLen*rounds). Note a 14000 byte password
takes ~1 second, 28000 is ~3 seconds, 56000 is ~11 seconds (results may vary depending on CPU and
sha256crypt vs sha512crypt). Ignoring bcrypt: sha256crypt and sha512crypt are the only other algos
that are not horrible and they are still very bad.
> > Since password_verify() and password_needs_rehash() already supports hashes created with
> > crypt(), the only thing needed to do is remove crypt().
>
> Removing it would cause serious BC issues with no practical gain.
What are "BC issues"?... Backward compatibility issues?
If that's the case, you may not know that password_verify() can verify all password hashes
created by crypt(). The whole point of deprecating and finally removing crypt() is that users can no
longer create bad password hashes. This is a massive gain in security. It's like removing
mcrypt which removed people's ability to ECB encrypt data. Sure there are very limited uses
that are secure but 99.9999% are crypto101 errors.
Also the *ONLY* non-broken password hash function that crypt() can do is bcrypt and
password_hash()/password_verify() is a better alternative for bcrypt hashes.
Basically crypt() serves no purpose besides as a legacy footgun.