在写这篇文章时,IETF推荐使用Argon2算法对密码进行散列。在这个例子中,我们将在我们的PHP7.2应用程序中使用Sodium来散列和验证密码,Argon2id 。
你可能需要在你的composer.json 文件中添加"ext-sodium": "*" 。
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,
],
];
}
}