01/03/2019 - PHP
As of writing this post, hashing passwords with Argon2 algorithm is recommended by IETF. In this example we are going to use Sodium to hash and verify passwords with Argon2id
in our PHP 7.2 application.
You might need to add "ext-sodium": "*"
to your composer.json
file.
class PasswordHasher
{
public function hash(string $plainPassword): string
{
return sodium_crypto_pwhash_str(
$plainPassword,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
}
public function verify(string $plainPassword, string $hashedPassword): bool
{
$result = sodium_crypto_pwhash_str_verify($hashedPassword, $plainPassword);
sodium_memzero($plainPassword);
return $result;
}
}
class PasswordHasherTest extends TestCase
{
public function testHash(): void
{
$hash = (new PasswordHasher())->hash('inanzzzinanzzz');
$this->assertStringStartsWith('$argon2id$v=19$m=65536,t=2,p=', $hash);
$this->assertSame(97, \strlen($hash));
}
/**
* @dataProvider passwordDataProvider
*/
public function testVerify(string $plainPassword, string $hashedPassword, bool $result): void
{
$this->assertSame($result, (new PasswordHasher())->verify($plainPassword, $hashedPassword));
}
public function passwordDataProvider(): array
{
return [
'Test with invalid password but valid hash' => [
'$plainPassword' => 'invalid_password',
'$hashedPassword' => '$argon2id$v=19$m=65536,t=2,p=1$Lum8Qyd9RS+q5wlDYHfACA$1YUvs5HNdq7MVY0YAVV7SxyrSp309CfyS3BUFfuR+GE',
'$result' => false,
],
'Test with valid password but invalid hash' => [
'$password' => 'inanzzzinanzzz',
'$hashedPassword' => 'invalid_hash',
'$result' => false,
],
'Test with valid password and hash' => [
'$password' => 'inanzzzinanzzz',
'$hashedPassword' => '$argon2id$v=19$m=65536,t=2,p=1$Lum8Qyd9RS+q5wlDYHfACA$1YUvs5HNdq7MVY0YAVV7SxyrSp309CfyS3BUFfuR+GE',
'$result' => true,
],
];
}
}