See PKCS #5 v2.0 http://tools.ietf.org/html/rfc2898 for implementation details.
The implementation is tested with test vectors from http://tools.ietf.org/html/rfc6070 .
If https://wiki.php.net/rfc/hash_pbkdf2 is ever part of PHP we should check for the
existence of hash_pbkdf2() and use it if available.
public static pbkdf2 ( string $password, string $salt, integer $iterationCount, integer $derivedKeyLength, string $algorithm = 'sha256' ) : string | ||
$password | string | Input string / password |
$salt | string | The salt |
$iterationCount | integer | Hash iteration count |
$derivedKeyLength | integer | Derived key length |
$algorithm | string | Hash algorithm to use, see hash_algos(), defaults to sha256 |
return | string | The computed derived key as raw binary data |
/** * @test * @dataProvider pbkdf2TestVectors */ public function pbkdf2TestVectorsAreCorrect($password, $salt, $iterationCount, $derivedKeyLength, $output) { $result = Algorithms::pbkdf2($password, $salt, $iterationCount, $derivedKeyLength, 'sha1'); $this->assertEquals(unpack('H*', pack('H*', $output)), unpack('H*', $result)); }
/** * Validate a password against a derived key (hashed password) and salt using PBKDF2. * Iteration count and algorithm have to match the parameters when generating the derived key. * * @param string $password The cleartext password * @param string $hashedPasswordAndSalt The derived key and salt in Base64 encoding as returned by hashPassword for verification * @param string $staticSalt Static salt that will be appended to the dynamic salt * @return boolean TRUE if the given password matches the hashed password * @throws \InvalidArgumentException */ public function validatePassword($password, $hashedPasswordAndSalt, $staticSalt = null) { $parts = explode(',', $hashedPasswordAndSalt); if (count($parts) !== 2) { throw new \InvalidArgumentException('The derived key with salt must contain a salt, separated with a comma from the derived key', 1306172911); } $dynamicSalt = base64_decode($parts[0]); $derivedKey = base64_decode($parts[1]); $derivedKeyLength = strlen($derivedKey); return $derivedKey === CryptographyAlgorithms::pbkdf2($password, $dynamicSalt . $staticSalt, $this->iterationCount, $derivedKeyLength, $this->algorithm); }