2022-12-14 16:38:46 +01:00
< ? php
namespace App\Security\Hasher ;
use App\SQLLogin\Exception\InvalidSQLPasswordException ;
2023-06-19 15:56:55 +02:00
use App\SQLLogin\Exception\SecurityPatternConfigurationException ;
use Psr\Log\LoggerInterface ;
2022-12-14 16:38:46 +01:00
use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException ;
use Symfony\Component\PasswordHasher\Hasher\CheckPasswordLengthTrait ;
use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface ;
class PasswordEncoder implements LegacyPasswordHasherInterface
{
use CheckPasswordLengthTrait ;
2022-12-16 15:00:14 +01:00
public const PASSWORD_PATTERN = 'password' ;
public const SALT_PATTERN = 'salt' ;
public const PEPPER_PATTERN = 'pepper' ;
2022-12-14 16:38:46 +01:00
protected ? string $pepper ;
2022-12-16 15:00:14 +01:00
protected array $hashAlgoLegacy ;
protected array $securityPattern ;
2022-12-14 16:38:46 +01:00
2023-06-19 15:56:55 +02:00
public function __construct ( ? string $pepper , string $hashAlgoLegacy , string $securityPattern , private LoggerInterface $loggerInterface )
2022-12-14 16:38:46 +01:00
{
$this -> pepper = $pepper ;
2022-12-16 15:00:14 +01:00
$this -> hashAlgoLegacy = explode ( ',' , $hashAlgoLegacy );
$this -> securityPattern = explode ( ',' , $securityPattern );
2022-12-14 16:38:46 +01:00
}
2022-12-16 15:00:14 +01:00
/**
2023-01-05 11:31:29 +01:00
* Pas utilisé , mais on doit le garder pour le implements
2022-12-16 15:00:14 +01:00
*/
2022-12-14 16:38:46 +01:00
public function hash ( string $plainPassword , string $salt = null ) : string
{
if ( $this -> isPasswordTooLong ( $plainPassword )) {
throw new InvalidPasswordException ();
}
2022-12-16 16:49:24 +01:00
return hash ( $plainPassword . $salt , $this -> hashAlgoLegacy [ 0 ]);
2022-12-14 16:38:46 +01:00
}
public function verify ( string $hashedPassword , string $plainPassword , string $salt = null ) : bool
{
if ( '' === $plainPassword || $this -> isPasswordTooLong ( $plainPassword )) {
return false ;
}
2022-12-16 15:00:14 +01:00
$completedPassword = $this -> getPasswordToHash ( $plainPassword , $salt );
2022-12-16 16:49:24 +01:00
foreach ( $this -> hashAlgoLegacy as $algo ) {
2023-01-11 10:30:24 +01:00
if ( 'ssha' === $algo && $this -> compareSsha ( $hashedPassword , $completedPassword )) {
return true ;
2023-01-06 17:06:29 +01:00
}
2022-12-16 16:49:24 +01:00
if ( $this -> isObsoleteAlgo ( $algo )) {
if ( hash_equals ( hash ( $algo , $completedPassword ), $hashedPassword )) {
return true ;
}
} else {
if ( password_verify ( $completedPassword , $hashedPassword )) {
return true ;
2022-12-16 15:00:14 +01:00
}
}
2022-12-14 16:38:46 +01:00
}
2022-12-16 16:49:24 +01:00
throw new InvalidSQLPasswordException ();
2022-12-14 16:38:46 +01:00
}
public function needsRehash ( string $hashedPassword ) : bool
{
return false ;
}
2022-12-16 15:00:14 +01:00
public function isObsoleteAlgo ( $algo ) : bool
{
return in_array ( $algo , hash_algos ());
}
/**
* Retourne la string à hasher en fonction du pattern indiqué
*
* @ param mixed $plainTextPassword
* @ param mixed $salt
*
* @ return string
*/
protected function getPasswordToHash ( $plainTextPassword , $salt )
{
$arrayRef = [
self :: PASSWORD_PATTERN => $plainTextPassword ,
self :: SALT_PATTERN => $salt ,
self :: PEPPER_PATTERN => $this -> pepper ,
];
foreach ( $this -> securityPattern as $term ) {
if ( self :: PEPPER_PATTERN !== $term && self :: PASSWORD_PATTERN !== $term && self :: SALT_PATTERN !== $term ) {
2023-06-19 15:56:55 +02:00
$this -> loggerInterface -> critical ( 'La configuration du security pattern est invalide, les termes autorisés sont : ' . self :: PASSWORD_PATTERN . ', ' . self :: SALT_PATTERN . ' et ' . self :: PEPPER_PATTERN );
throw new SecurityPatternConfigurationException ();
2022-12-16 15:00:14 +01:00
}
}
2022-12-16 15:39:42 +01:00
$completedPlainPassword = '' ;
2022-12-16 15:00:14 +01:00
foreach ( $this -> securityPattern as $term ) {
2022-12-16 15:39:42 +01:00
$completedPlainPassword .= $arrayRef [ $term ];
2022-12-16 15:00:14 +01:00
}
return $completedPlainPassword ;
}
2023-01-06 17:06:29 +01:00
protected function compareSsha ( $hashPassword , $plainPassword )
{
$base_64_hash_with_salt = substr ( $hashPassword , 6 );
$hash_with_salt = base64_decode ( $base_64_hash_with_salt );
$hash = substr ( $hash_with_salt , 0 , 20 );
$salt = substr ( $hash_with_salt , 20 );
// hash given password
$hash_given = sha1 ( $plainPassword . $salt , true );
return $hash == $hash_given ;
}
2022-12-14 16:38:46 +01:00
}