$this->cost($options), ]); if (!$hash) { throw new HashFailedException(); } return $hash; } /** * Verify a plaintext password against the user's hashed password. * * @param string $password The plaintext password to verify. * @param string $hash The hash to compare against. * @param array $options * @return boolean True if the password matches, false otherwise. */ public function verify($password, $hash, array $options = []) { $hashType = $this->getHashType($hash); if ($hashType == 'sha1') { // Legacy UserCake passwords $salt = substr($hash, 0, 25); // Extract the salt from the hash $inputHash = $salt . sha1($salt . $password); return (hash_equals($inputHash, $hash) === TRUE); } else if ($hashType == 'legacy') { // Homegrown implementation (assuming that current install has been using a cost parameter of 12) // Used for manual implementation of bcrypt. // Note that this legacy hashing put the salt at the _end_ for some reason. $salt = substr($hash, 60); $inputHash = crypt($password, '$2y$12$' . $salt); $correctHash = substr($hash, 0, 60); return (hash_equals($inputHash, $correctHash) === TRUE); } // Modern implementation return password_verify($password, $hash); } /** * Extract the cost value from the options array. * * @param array $options * @return int */ protected function cost(array $options = []) { return isset($options['rounds']) ? $options['rounds'] : $this->defaultRounds; } }