-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from jeremykendall/example/daniel-karps-rehash-…
…upgrade-scenario Adds legacySalt argument to PasswordValidatorInterface
- Loading branch information
Showing
10 changed files
with
269 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
tests/JeremyKendall/Password/Tests/Decorator/KarptoniteRehashUpgradeDecoratorTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
<?php | ||
|
||
/** | ||
* Password Validator | ||
* | ||
* @link http://github.com/jeremykendall/password-validator Canonical source repo | ||
* @copyright Copyright (c) 2014 Jeremy Kendall (http://about.me/jeremykendall) | ||
* @license http://github.com/jeremykendall/password-validator/blob/master/LICENSE MIT | ||
*/ | ||
|
||
namespace JeremyKendall\Password\Tests\Decorator; | ||
|
||
use JeremyKendall\Password\Decorator\UpgradeDecorator; | ||
use JeremyKendall\Password\Result as ValidationResult; | ||
|
||
/** | ||
* This test validates the upgrade scenario outlined in Daniel Karp's blog post | ||
* {@link http://bit.ly/T0gwRN "Rehashing Password Hashes"}. | ||
* | ||
* In order to properly validate this scenario, the $validationCallback should | ||
* be written to use {@link http://php.net/password_verify password_verify} to | ||
* test the plain text password's legacy hash against the upgraded, persisted | ||
* hash. | ||
*/ | ||
class KarptoniteRehashUpgradeDecoratorTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
private $decorator; | ||
private $decoratedValidator; | ||
private $validationCallback; | ||
private $plainTextPassword; | ||
private $legacySalt; | ||
private $upgradedLegacyHash; | ||
|
||
protected function setUp() | ||
{ | ||
parent::setUp(); | ||
|
||
$this->validationCallback = function ($credential, $passwordHash, $salt) { | ||
// Recreate the legacy hash. This was the persisted password hash | ||
// prior to upgrading. | ||
$legacyHash = hash('sha512', $credential . $salt); | ||
|
||
// Now test the old hash against the new, upgraded hash | ||
if (password_verify($legacyHash, $passwordHash)) { | ||
return true; | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
$interface = 'JeremyKendall\Password\PasswordValidatorInterface'; | ||
$this->decoratedValidator = $this->getMockBuilder($interface) | ||
->disableOriginalConstructor() | ||
->getMock(); | ||
|
||
$this->decorator = new UpgradeDecorator( | ||
$this->decoratedValidator, | ||
$this->validationCallback | ||
); | ||
|
||
$this->plainTextPassword = 'password'; | ||
$this->legacySalt = mt_rand(1000, 1000000); | ||
|
||
$legacyHash = hash('sha512', $this->plainTextPassword . $this->legacySalt); | ||
$this->upgradedLegacyHash = password_hash($legacyHash, PASSWORD_DEFAULT); | ||
} | ||
|
||
public function testRehashingPasswordHashesScenarioCredentialIsValid() | ||
{ | ||
$upgradeValidatorRehash = password_hash( | ||
$this->plainTextPassword, | ||
PASSWORD_DEFAULT, | ||
array( | ||
'cost' => 4, | ||
'salt' => 'CostAndSaltForceRehash', | ||
) | ||
); | ||
$finalValidatorRehash = password_hash($this->plainTextPassword, PASSWORD_DEFAULT); | ||
|
||
$validResult = new ValidationResult( | ||
ValidationResult::SUCCESS_PASSWORD_REHASHED, | ||
$finalValidatorRehash | ||
); | ||
|
||
$this->decoratedValidator->expects($this->once()) | ||
->method('isValid') | ||
->with($this->plainTextPassword, $upgradeValidatorRehash, $this->legacySalt) | ||
->will($this->returnValue($validResult)); | ||
|
||
$result = $this->decorator->isValid( | ||
$this->plainTextPassword, | ||
$this->upgradedLegacyHash, | ||
$this->legacySalt | ||
); | ||
|
||
$this->assertTrue($result->isValid()); | ||
$this->assertEquals( | ||
ValidationResult::SUCCESS_PASSWORD_REHASHED, | ||
$result->getCode() | ||
); | ||
|
||
// Final rehashed password is a valid hash | ||
$this->assertTrue( | ||
password_verify($this->plainTextPassword, $result->getPassword()) | ||
); | ||
} | ||
|
||
public function testRehashingPasswordHashesScenarioCredentialIsNotValid() | ||
{ | ||
$wrongPlainTextPassword = 'i-forgot-my-password'; | ||
|
||
$invalidResult = new ValidationResult( | ||
ValidationResult::FAILURE_PASSWORD_INVALID | ||
); | ||
|
||
$this->decoratedValidator->expects($this->never()) | ||
->method('rehash'); | ||
|
||
$this->decoratedValidator->expects($this->once()) | ||
->method('isValid') | ||
->with($wrongPlainTextPassword, $this->upgradedLegacyHash, $this->legacySalt) | ||
->will($this->returnValue($invalidResult)); | ||
|
||
$result = $this->decorator->isValid( | ||
$wrongPlainTextPassword, | ||
$this->upgradedLegacyHash, | ||
$this->legacySalt | ||
); | ||
|
||
$this->assertFalse($result->isValid()); | ||
$this->assertEquals( | ||
ValidationResult::FAILURE_PASSWORD_INVALID, | ||
$result->getCode() | ||
); | ||
} | ||
|
||
/** | ||
* @dataProvider callbackDataProvider | ||
*/ | ||
public function testVerifyValidationCallback($password, $result) | ||
{ | ||
$isValid = call_user_func( | ||
$this->validationCallback, | ||
$password, | ||
$this->upgradedLegacyHash, | ||
$this->legacySalt | ||
); | ||
|
||
$this->assertEquals($result, $isValid); | ||
} | ||
|
||
public function callbackDataProvider() | ||
{ | ||
return array( | ||
array('password', true), | ||
array('wrong-password', false), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.