PHPackages                             jeremykendall/password-validator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. jeremykendall/password-validator

ActiveLibrary[Security](/categories/security)

jeremykendall/password-validator
================================

Password Validator validates password\_hash generated passwords, rehashes passwords as necessary, and will upgrade legacy passwords.

3.0.4(10y ago)14469.9k↓32.1%16[1 PRs](https://github.com/jeremykendall/password-validator/pulls)3MITPHPPHP &gt;=5.3.7

Since Jan 4Pushed 8y ago7 watchersCompare

[ Source](https://github.com/jeremykendall/password-validator)[ Packagist](https://packagist.org/packages/jeremykendall/password-validator)[ Docs](https://github.com/jeremykendall/password-validator)[ RSS](/packages/jeremykendall-password-validator/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (10)Dependencies (4)Versions (18)Used By (3)

Password Validator [![Build Status](https://camo.githubusercontent.com/3df4c34bd6016617dcabee1b787f161a23fd9adaf9e012850df85c52694c3272/68747470733a2f2f7472617669732d63692e6f72672f6a6572656d796b656e64616c6c2f70617373776f72642d76616c696461746f722e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/jeremykendall/password-validator) [![Coverage Status](https://camo.githubusercontent.com/3e988e0db8eb2f9343f2303606ce1a994e7befcabb9214824b195a461bd9ce03/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6a6572656d796b656e64616c6c2f70617373776f72642d76616c696461746f722f62616467652e706e673f6272616e63683d6d6173746572)](https://coveralls.io/r/jeremykendall/password-validator?branch=master)
==========================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#password-validator--)

**Password Validator** *validates* [`password_hash`](http://www.php.net/manual/en/function.password-hash.php) generated passwords, *rehashes*passwords as necessary, and will *upgrade* legacy passwords.

Read the introductory blog post: [PHP Password Hashing: A Dead Simple Implementation](http://jeremykendall.net/2014/01/04/php-password-hashing-a-dead-simple-implementation/)

*Password Validator is available for all versions of PHP &gt;= 5.3.7.*

Motivation
----------

[](#motivation)

Why? Because one must always[ encrypt passwords for highest level of security](http://csiphp.com/blog/2012/02/16/encrypt-passwords-for-highest-level-of-security/), and the new [PHP password hashing](http://www.php.net/manual/en/ref.password.php) functions provide that level of security.

The **Password Validator** library makes it (more) trivial to use the new password hash functions in your application. Just add the validator to your authentication script and you're up and running.

The really big deal here is the **ease of upgrading** from your current legacy hashes to the new, more secure PHP password hash hashes. Simply wrap the `PasswordValidator` in the `UpgradeDecorator`, provide a callback to validate your existing password hashing scheme, and BOOM, you're using new password hashes in a manner *completely transparent* to your application's users. Nifty, huh?

Usage
-----

[](#usage)

### Password Validation

[](#password-validation)

If you're already using [`password_hash`](http://www.php.net/manual/en/function.password-hash.php) generated passwords in your application, you need do nothing more than add the validator in your authentication script. The validator uses [`password_verify`](http://www.php.net/manual/en/function.password-verify.php) to test the validity of the provided password hash.

```
use JeremyKendall\Password\PasswordValidator;

$validator = new PasswordValidator();
$result = $validator->isValid($_POST['password'], $hashedPassword);

if ($result->isValid()) {
    // password is valid
}
```

If your application requires options other than the `password_hash` defaults, you can set the `cost` option with `PasswordValidator::setOptions()`.

```
$options = array(
    'cost' => 11
);
$validator->setOptions($options);
```

**IMPORTANT**: `PasswordValidator` uses a default cost of `10`. If your existing hash implementation requires a different cost, make sure to specify it using `PasswordValidator::setOptions()`. If you do not do so, all of your passwords will be rehashed using a cost of `10`.

### Rehashing

[](#rehashing)

Each valid password is tested using [`password_needs_rehash`](http://www.php.net/manual/en/function.password-needs-rehash.php). If a rehash is necessary, the valid password is hashed using `password_hash` with the provided options. The result code `Result::SUCCESS_PASSWORD_REHASHED` will be returned from `Result::getCode()` and the new password hash is available via `Result::getPassword()`.

```
if ($result->getCode() === Result::SUCCESS_PASSWORD_REHASHED) {
    $rehashedPassword = $result->getPassword();
    // Persist rehashed password
}
```

**IMPORTANT**: If the password has been rehashed, it's critical that you persist the updated password hash. Otherwise, what's the point, right?

### Upgrading Legacy Passwords

[](#upgrading-legacy-passwords)

You can use the `PasswordValidator` whether or not you're currently using `password_hash` generated passwords. The validator will transparently upgrade your current legacy hashes to the new `password_hash` generated hashes as each user logs in. All you need to do is provide a validator callback for your password hash and then [decorate](http://en.wikipedia.org/wiki/Decorator_pattern) the validator with the `UpgradeDecorator`.

```
use JeremyKendall\Password\Decorator\UpgradeDecorator;

// Example callback to validate a sha512 hashed password
$callback = function ($password, $passwordHash, $salt) {
    if (hash('sha512', $password . $salt) === $passwordHash) {
        return true;
    }

    return false;
};

$validator = new UpgradeDecorator(new PasswordValidator(), $callback);
$result = $validator->isValid('password', 'password-hash', 'legacy-salt');
```

The `UpgradeDecorator` will validate a user's current password using the provided callback. If the user's password is valid, it will be hashed with `password_hash` and returned in the `Result` object, as above.

All password validation attempts will eventually pass through the `PasswordValidator`. This allows a password that has already been upgraded to be properly validated, even when using the `UpgradeDecorator`.

#### Alternate Upgrade Technique

[](#alternate-upgrade-technique)

Rather than upgrading each user's password as they log in, it's possible to preemptively rehash persisted legacy hashes all at once. `PasswordValidator`and the `UpgradeDecorator` can then be used to validate passwords against the rehashed legacy hashes, at which point the user's plain text password will be hashed with `password_hash`, completing the upgrade process.

For more information on this technique, please see Daniel Karp's [Rehashing Password Hashes](http://karptonite.com/2014/05/11/rehashing-password-hashes/) blog post, and review [`JeremyKendall\Password\Tests\Decorator\KarptoniteRehashUpgradeDecoratorTest`](tests/JeremyKendall/Password/Tests/Decorator/KarptoniteRehashUpgradeDecoratorTest.php)to see a sample implementation.

### Persisting Rehashed Passwords

[](#persisting-rehashed-passwords)

Whenever a validation attempt returns `Result::SUCCESS_PASSWORD_REHASHED`, it's important to persist the updated password hash.

```
if ($result->getCode() === Result::SUCCESS_PASSWORD_REHASHED) {
    $rehashedPassword = $result->getPassword();
    // Persist rehashed password
}
```

While you can always perform the test and then update your user database manually, if you choose to use the **Storage Decorator** all rehashed passwords will be automatically persisted.

The Storage Decorator takes two constructor arguments: An instance of `PasswordValidatorInterface` and an instance of the `JeremyKendall\Password\Storage\StorageInterface`.

#### StorageInterface

[](#storageinterface)

The `StorageInterface` includes a single method, `updatePassword()`. A class honoring the interface might look like this:

```
