diff --git a/core/modules/system/lib/Drupal/system/Tests/System/PasswordHashingTest.php b/core/modules/system/lib/Drupal/system/Tests/System/PasswordHashingTest.php deleted file mode 100644 index 53ff2fc..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/System/PasswordHashingTest.php +++ /dev/null @@ -1,67 +0,0 @@ - 'Password hashing', - 'description' => 'Password hashing unit tests.', - 'group' => 'System', - ); - } - - /** - * Test password hashing. - */ - function testPasswordHashing() { - // Set a log2 iteration count that is deliberately out of bounds to test - // that it is corrected to be within bounds. - $password_hasher = new PhpassHashedPassword(1); - // Set up a fake $account with a password 'baz', hashed with md5. - $password = 'baz'; - $account = entity_create('user', array('name' => 'foo', 'pass' => md5($password))); - // The md5 password should be flagged as needing an update. - $this->assertTrue($password_hasher->userNeedsNewHash($account), 'User with md5 password needs a new hash.'); - // Re-hash the password. - $old_hash = $account->getPassword(); - $account->setPassword($password_hasher->hash($password)); - $this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $password_hasher::MIN_HASH_COUNT, 'Re-hashed password has the minimum number of log2 iterations.'); - $this->assertTrue($account->getPassword() != $old_hash, 'Password hash changed.'); - $this->assertTrue($password_hasher->check($password, $account), 'Password check succeeds.'); - // Since the log2 setting hasn't changed and the user has a valid password, - // $password_hasher->userNeedsNewHash() should return FALSE. - $this->assertFalse($password_hasher->userNeedsNewHash($account), 'User does not need a new hash.'); - - // Increment the log2 iteration to MIN + 1. - $password_hasher = new PhpassHashedPassword($password_hasher::MIN_HASH_COUNT + 1); - $this->assertTrue($password_hasher->userNeedsNewHash($account), 'User needs a new hash after incrementing the log2 count.'); - // Re-hash the password. - $old_hash = $account->getPassword(); - $account->setPassword($password_hasher->hash($password)); - $this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $password_hasher::MIN_HASH_COUNT + 1, 'Re-hashed password has the correct number of log2 iterations.'); - $this->assertTrue($account->getPassword() != $old_hash, 'Password hash changed again.'); - // Now the hash should be OK. - $this->assertFalse($password_hasher->userNeedsNewHash($account), 'Re-hashed password does not need a new hash.'); - $this->assertTrue($password_hasher->check($password, $account), 'Password check succeeds with re-hashed password.'); - } -} diff --git a/core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php b/core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php new file mode 100644 index 0000000..bea698a --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php @@ -0,0 +1,152 @@ + 'Password hashing', + 'description' => 'Password hashing unit tests.', + 'group' => 'System', + ); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->user = $this->getMockBuilder('Drupal\user\Entity\User')->disableOriginalConstructor()->getMock(); + $this->passwordHasher = new PhpassHashedPassword(1); + } + + /** + * Tests the hash count boundaries are enforced. + */ + public function testWithinBounds() { + $hasher = new FakePhpassHashedPassword(); + $this->assertEquals(PhpassHashedPassword::MIN_HASH_COUNT, $hasher->enforceLog2Boundaries(1), "Min hash count enforced"); + $this->assertEquals(PhpassHashedPassword::MAX_HASH_COUNT, $hasher->enforceLog2Boundaries(100), "Max hash count enforced"); + } + + + /** + * Test a password needs update. + */ + public function testPasswordNeedsUpdate() { + $this->user->expects($this->any()) + ->method('getPassword') + ->will($this->returnValue($this->md5Password)); + // The md5 password should be flagged as needing an update. + $this->assertTrue($this->passwordHasher->userNeedsNewHash($this->user), 'User with md5 password needs a new hash.'); + } + + /** + * Test password hashing. + */ + public function testPasswordHashing() { + $this->hashedPassword = $this->passwordHasher->hash($this->password); + $this->user->expects($this->any()) + ->method('getPassword') + ->will($this->returnValue($this->hashedPassword)); + $this->assertSame($this->passwordHasher->getCountLog2($this->hashedPassword), PhpassHashedPassword::MIN_HASH_COUNT, 'Hashed password has the minimum number of log2 iterations.'); + $this->assertTrue($this->hashedPassword != $this->md5Password, 'Password hash changed.'); + $this->assertTrue($this->passwordHasher->check($this->password, $this->user), 'Password check succeeds.'); + // Since the log2 setting hasn't changed and the user has a valid password, + // userNeedsNewHash() should return FALSE. + $this->assertFalse($this->passwordHasher->userNeedsNewHash($this->user), 'User does not need a new hash.'); + } + + /** + * Tests password rehashing. + */ + public function testPasswordRehashing() { + + // Increment the log2 iteration to MIN + 1. + $this->passwordHasher = new PhpassHashedPassword(PhpassHashedPassword::MIN_HASH_COUNT + 1); + $this->assertTrue($this->passwordHasher->userNeedsNewHash($this->user), 'User needs a new hash after incrementing the log2 count.'); + // Re-hash the password. + $rehashed_password = $this->passwordHasher->hash($this->password); + + $this->user->expects($this->any()) + ->method('getPassword') + ->will($this->returnValue($rehashed_password)); + $this->assertSame($this->passwordHasher->getCountLog2($rehashed_password), PhpassHashedPassword::MIN_HASH_COUNT + 1, 'Re-hashed password has the correct number of log2 iterations.'); + $this->assertTrue($rehashed_password != $this->hashedPassword, 'Password hash changed again.'); + + // Now the hash should be OK. + $this->assertFalse($this->passwordHasher->userNeedsNewHash($this->user), 'Re-hashed password does not need a new hash.'); + $this->assertTrue($this->passwordHasher->check($this->password, $this->user), 'Password check succeeds with re-hashed password.'); + } + +} + +/** + * A fake class for tests. + */ +class FakePhpassHashedPassword extends PhpassHashedPassword { + + function __construct() { + // noop + } + + // Expose this method as public for tests. + public function enforceLog2Boundaries($count_log2) { + return parent::enforceLog2Boundaries($count_log2); + } + +}