Skip to content

Commit

Permalink
[10.x] Hash::isHashed($value) (#47197)
Browse files Browse the repository at this point in the history
* isHashed-method

* Fix tests

* Extra test

* Fix linting issues

* Update HashManager.php

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
gdebrauwer and taylorotwell authored May 24, 2023
1 parent c95df92 commit 03a47ab
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1310,7 +1310,7 @@ public static function encryptUsing($encrypter)
*/
protected function castAttributeAsHashedString($key, $value)
{
return $value !== null && password_get_info($value)['algo'] === null ? Hash::make($value) : $value;
return $value !== null && ! Hash::isHashed($value) ? Hash::make($value) : $value;
}

/**
Expand Down
11 changes: 11 additions & 0 deletions src/Illuminate/Hashing/HashManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ public function needsRehash($hashedValue, array $options = [])
return $this->driver()->needsRehash($hashedValue, $options);
}

/**
* Determine if a given string is already hashed.
*
* @param string $value
* @return bool
*/
public function isHashed($value)
{
return password_get_info($value)['algo'] !== null;
}

/**
* Get the default driver name.
*
Expand Down
23 changes: 23 additions & 0 deletions tests/Hashing/HasherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,29 @@

namespace Illuminate\Tests\Hashing;

use Illuminate\Config\Repository as Config;
use Illuminate\Container\Container;
use Illuminate\Hashing\Argon2IdHasher;
use Illuminate\Hashing\ArgonHasher;
use Illuminate\Hashing\BcryptHasher;
use Illuminate\Hashing\HashManager;
use PHPUnit\Framework\TestCase;
use RuntimeException;

class HasherTest extends TestCase
{
public $hashManager;

public function setUp(): void
{
parent::setUp();

$container = Container::setInstance(new Container);
$container->singleton('config', fn () => new Config());

$this->hashManager = new HashManager($container);
}

public function testEmptyHashedValueReturnsFalse()
{
$hasher = new BcryptHasher();
Expand Down Expand Up @@ -39,6 +54,7 @@ public function testBasicBcryptHashing()
$this->assertFalse($hasher->needsRehash($value));
$this->assertTrue($hasher->needsRehash($value, ['rounds' => 1]));
$this->assertSame('bcrypt', password_get_info($value)['algoName']);
$this->assertTrue($this->hashManager->isHashed($value));
}

public function testBasicArgon2iHashing()
Expand All @@ -50,6 +66,7 @@ public function testBasicArgon2iHashing()
$this->assertFalse($hasher->needsRehash($value));
$this->assertTrue($hasher->needsRehash($value, ['threads' => 1]));
$this->assertSame('argon2i', password_get_info($value)['algoName']);
$this->assertTrue($this->hashManager->isHashed($value));
}

public function testBasicArgon2idHashing()
Expand All @@ -61,6 +78,7 @@ public function testBasicArgon2idHashing()
$this->assertFalse($hasher->needsRehash($value));
$this->assertTrue($hasher->needsRehash($value, ['threads' => 1]));
$this->assertSame('argon2id', password_get_info($value)['algoName']);
$this->assertTrue($this->hashManager->isHashed($value));
}

/**
Expand Down Expand Up @@ -98,4 +116,9 @@ public function testBasicArgon2idVerification()
$bcryptHashed = $bcryptHasher->make('password');
(new Argon2IdHasher(['verify' => true]))->check('password', $bcryptHashed);
}

public function testIsHashedWithNonHashedValue()
{
$this->assertFalse($this->hashManager->isHashed('foo'));
}
}
14 changes: 11 additions & 3 deletions tests/Integration/Database/EloquentModelHashedCastingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ protected function defineDatabaseMigrationsAfterDatabaseRefreshed()

public function testHashed()
{
$this->hasher->expects('isHashed')
->with('this is a password')
->andReturnFalse();

$this->hasher->expects('make')
->with('this is a password')
->andReturn('hashed-password');
Expand All @@ -47,14 +51,18 @@ public function testHashed()

public function testNotHashedIfAlreadyHashed()
{
$this->hasher->expects('isHashed')
->with('already-hashed-password')
->andReturnTrue();

$subject = HashedCast::create([
'password' => $hashedPassword = '$argon2i$v=19$m=65536,t=4,p=1$RHFPR1Zjc1p5cUVXTVJEcg$ooJoZb7NOa3r35WeeDRvnFwBTfaqlbbo1WcdJP5nPp8',
'password' => 'already-hashed-password',
]);

$this->assertSame($hashedPassword, $subject->password);
$this->assertSame('already-hashed-password', $subject->password);
$this->assertDatabaseHas('hashed_casts', [
'id' => $subject->id,
'password' => $hashedPassword,
'password' => 'already-hashed-password',
]);
}

Expand Down

0 comments on commit 03a47ab

Please sign in to comment.