42 lines
1.1 KiB
PHP
42 lines
1.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Security;
|
|
|
|
class Pbkdf2Hasher
|
|
{
|
|
public function hash(string $password, string $algo = 'sha256', int $iterations = 100000, int $length = 64): string
|
|
{
|
|
$salt = random_bytes(16);
|
|
$saltHex = bin2hex($salt);
|
|
|
|
$derived = hash_pbkdf2($algo, $password, $salt, $iterations, $length, true);
|
|
$derivedHex = bin2hex($derived);
|
|
|
|
return implode('$', [$algo, $iterations, $saltHex, $derivedHex]);
|
|
}
|
|
|
|
public function verify(string $password, string $storedHash): bool
|
|
{
|
|
$parts = explode('$', $storedHash);
|
|
if (count($parts) !== 4) {
|
|
return false;
|
|
}
|
|
|
|
[$algo, $iterations, $saltHex, $derivedHex] = $parts;
|
|
if (strlen($saltHex) % 2 !== 0 || strlen($derivedHex) % 2 !== 0) {
|
|
return false;
|
|
}
|
|
|
|
$salt = hex2bin($saltHex);
|
|
$derived = hex2bin($derivedHex);
|
|
if ($salt === false || $derived === false) {
|
|
return false;
|
|
}
|
|
|
|
$length = strlen($derived);
|
|
$calc = hash_pbkdf2($algo, $password, $salt, (int) $iterations, $length, true);
|
|
|
|
return hash_equals($derived, $calc);
|
|
}
|
|
}
|