So I heard that PHP 7.2 introduced the new Argon2 algorithm. But I'm confused on how I can use it with my existing code. For instance, I have this
$password = password_hash('somepassword', PASSWORD_DEFAULT, ['cost' => 12]);
Does PASSWORD_DEFAULT
now use Argon2? What, if anything, do I need to change with password_verify
? Is bcrypt considered insecure now?
What is Argon2? Is bcrypt bad now?
Prior to PHP 7.2, the only hashing algorithm
password_hash
used was bcrypt. As of this writing, bcrypt is still considered a strong hash, especially compared to its predecessors,md5
andsha1
(both of which are insecure because they are fast). Argon2 is simply a costlier algorithm to brute forceBcrypt is still an acceptable hash for passwords. There's no need to switch if you don't want to (as of the 7.2.0 release). Also,
PASSWORD_DEFAULT
should only change (per PHP Internals policy) on the next full release (7.3.0 or higher). If you want to ensure you continue with only bcrypt, you can usePASSWORD_BCRYPT
instead. This is unnecessary, however, as we'll discuss below.How do you use Argon2?
First, we'll switch the second argument of
password_hash
over to one of these to constantsPASSWORD_ARGON2I
- PHP 7.2.0+PASSWORD_ARGON2ID
- PHP 7.3.0+ (preferred if available, see notes below)and then we'll need to change our options. bcrypt uses
cost
as the parameter for how many times it iterates over the password (higher cost = longer hashing time). There's different cost factors, howeverFrom the manual we see what these options do
memory_cost
- Maximum memory (in bytes) that may be used to compute the Argon2 hash (default 1024)time_cost
- Maximum amount of time it may take to compute the Argon2 hash (default 2)threads
- Number of threads to use for computing the Argon2 hash (default 2)Understand, before you go changing these, that a higher cost here will slow down your script. You'll want to run a test on your server to find a setting that works best for you. This is typically by looping over several iterations of a given cost. The PHP manual gives an example of this if you need one.
Also note that, while bcrypt stores 60 characters, Argon2 can require more than that. You should, ideally, make your password field store 255 characters.
What do we change in
password_verify
?The answer here is... nothing. Understand that
password_verify
is smart enough to figure out what algorithm was used and handle it appropriately. As mentioned above, this means that if you are usingPASSWORD_DEFAULT
, the default can change and not negatively affect you (although you may need to adjust the cost parameters).password_verify
simply requires an algorithm it supports. If you switch from bcrypt to Argon2, both will verify the same way, as all the necessary data (salt, hash and cost) are stored for you.If you want to upgrade the hashes from bcrypt, you can do this when a user successfully logs in (and thus supplied you with the un-hashed password). Simply check if your hash starts with
$2y$
(the bcrypt marker). If it does, pass the supplied password topassword_hash
again, but with the Argon2 arguments, and save it to the password field of the logged-in user.What is Argon2ID?
Introduced in PHP 7.3, Argon2ID makes some improvements over Argon2I as noted in this Crypto.SE question
Argon2ID works with the same arguments that Argon2I works with.