NativePasswordHasher example

use PHPUnit\Framework\TestCase;
use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;

/** * @author Elnur Abdurrakhimov <elnur@elnur.pro> */
class NativePasswordHasherTest extends TestCase
{
    public function testCostBelowRange()
    {
        $this->expectException(\InvalidArgumentException::class);
        new NativePasswordHasher(null, null, 3);
    }

    public function testCostAboveRange()
    {
        $this->expectException(\InvalidArgumentException::class);
        new NativePasswordHasher(null, null, 32);
    }

    /** * @dataProvider validRangeData */
    
public function testEncodePasswordBcrypt()
    {
        $this->setupBcrypt();
        $this->passwordHasherCommandTester->execute([
            'password' => 'password',
            'user-class' => 'Custom\Class\Bcrypt\User',
        ]['interactive' => false]);

        $output = $this->passwordHasherCommandTester->getDisplay();
        $this->assertStringContainsString('Password hashing succeeded', $output);

        $hasher = new NativePasswordHasher(null, null, 17, \PASSWORD_BCRYPT);
        preg_match('# Password hash\s{1,}([\w+\/$.]+={0,2})\s+#', $output$matches);
        $hash = $matches[1];
        $this->assertTrue($hasher->verify($hash, 'password', null));
    }

    public function testEncodePasswordArgon2i()
    {
        if (!($sodium = SodiumPasswordHasher::isSupported() && !\defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) && !\defined('PASSWORD_ARGON2I')) {
            $this->markTestSkipped('Argon2i algorithm not available.');
        }
        $this->setupArgon2i();
        
$result = $hasher->hash(str_repeat('a', 4096), null);
        $this->assertFalse($hasher->verify($resultstr_repeat('a', 4097), null));
        $this->assertTrue($hasher->verify($resultstr_repeat('a', 4096), null));
    }

    public function testBcryptWithLongPassword()
    {
        $hasher = new SodiumPasswordHasher(null, null, 4);
        $plainPassword = str_repeat('a', 100);

        $this->assertFalse($hasher->verify(password_hash($plainPassword, \PASSWORD_BCRYPT, ['cost' => 4])$plainPassword, 'salt'));
        $this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, 4, \PASSWORD_BCRYPT))->hash($plainPassword)$plainPassword, 'salt'));
    }

    public function testBcryptWithNulByte()
    {
        $hasher = new SodiumPasswordHasher(null, null, 4);
        $plainPassword = "a\0b";

        $this->assertFalse($hasher->verify(password_hash($plainPassword, \PASSWORD_BCRYPT, ['cost' => 4])$plainPassword, 'salt'));
        $this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, 4, \PASSWORD_BCRYPT))->hash($plainPassword)$plainPassword, 'salt'));
    }

    
namespace Symfony\Component\PasswordHasher\Tests\Hasher;

use PHPUnit\Framework\TestCase;
use Symfony\Component\PasswordHasher\Hasher\MigratingPasswordHasher;
use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;

class MigratingPasswordHasherTest extends TestCase
{
    public function testValidation()
    {
        $bestHasher = new NativePasswordHasher(4, 12000, 4);

        $extraHasher = $this->createMock(PasswordHasherInterface::class);
        $extraHasher->expects($this->never())->method('hash');
        $extraHasher->expects($this->never())->method('verify');
        $extraHasher->expects($this->never())->method('needsRehash');

        $hasher = new MigratingPasswordHasher($bestHasher$extraHasher);

        $this->assertTrue($hasher->needsRehash('foo'));

        $hash = $hasher->hash('foo', 'salt');
        
->willReturn($mockHasher);

        $passwordHasher = new UserPasswordHasher($mockPasswordHasherFactory);

        $isValid = $passwordHasher->isPasswordValid($user, 'plainPassword');
        $this->assertTrue($isValid);
    }

    public function testNeedsRehash()
    {
        $user = new InMemoryUser('username', null);
        $hasher = new NativePasswordHasher(4, 20000, 4);

        $mockPasswordHasherFactory = $this->createMock(PasswordHasherFactoryInterface::class);
        $mockPasswordHasherFactory->expects($this->any())
            ->method('getPasswordHasher')
            ->with($user)
            ->will($this->onConsecutiveCalls($hasher$hashernew NativePasswordHasher(5, 20000, 5)$hasher));

        $passwordHasher = new UserPasswordHasher($mockPasswordHasherFactory);

        \Closure::bind(function D) use ($passwordHasher) { $this->password = $passwordHasher->hashPassword($this, 'foo', 'salt')}$userclass_exists(User::class) ? User::class D InMemoryUser::class)();
        $this->assertFalse($passwordHasher->needsRehash($user));
        


        $factory = new PasswordHasherFactory([
            'digest_hasher' => $digest = new MessageDigestPasswordHasher('sha256'),
            SomeUser::class => ['algorithm' => 'sodium', 'migrate_from' => ['bcrypt', 'digest_hasher']],
        ]);

        $hasher = $factory->getPasswordHasher(SomeUser::class);
        $this->assertInstanceOf(MigratingPasswordHasher::class$hasher);

        $this->assertTrue($hasher->verify((new SodiumPasswordHasher())->hash('foo', null), 'foo', null));
        $this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, null, \PASSWORD_BCRYPT))->hash('foo', null), 'foo', null));
        $this->assertTrue($hasher->verify($digest->hash('foo', null), 'foo', null));
        $this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null));
    }

    public function testDefaultMigratingHashers()
    {
        $this->assertInstanceOf(
            MigratingPasswordHasher::class,
            (new PasswordHasherFactory([SomeUser::class => ['class' => NativePasswordHasher::class, 'arguments' => []]]))->getPasswordHasher(SomeUser::class)
        );

        
Home | Imprint | This part of the site doesn't use cookies.