20steps/bricks-scrypt-password-encoder-bundle
Installation
composer require usu/scrypt-password-encoder-bundle
Add the bundle to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
// config/bundles.php
return [
// ...
Usu\ScryptPasswordEncoderBundle\UsuScryptPasswordEncoderBundle::class => ['all' => true],
];
Configure in config/packages/security.yaml
security:
encoders:
App\Entity\User: 'scrypt'
First Use Case
Register a user via Symfony’s UserPasswordHasherInterface (or EncoderFactory in older versions):
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
$hasher = $this->get('security.user_password_hasher');
$hashedPassword = $hasher->hashPassword($user, 'plainPassword');
Password Hashing
Use the built-in UserPasswordHasherInterface (Symfony 5+) or EncoderFactory (Symfony 2/3) to hash passwords:
// Symfony 5+
$hasher = $this->get('security.user_password_hasher');
$hashed = $hasher->hashPassword($user, $plainPassword);
// Symfony 2/3 (legacy)
$encoder = $this->get('security.encoder_factory')->getEncoder($user);
$hashed = $encoder->encodePassword($plainPassword, $user->getSalt());
Verification
if ($hasher->isPasswordValid($user, $plainPassword)) {
// Password matches
}
Custom User Entity
Ensure your User entity implements PasswordAwareInterface (Symfony 5+) or has getPassword()/setPassword() methods:
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
class User implements PasswordAuthenticatedUserInterface {
private $password;
public function getPassword(): ?string { ... }
public function setPassword(string $password): void { ... }
}
$users = $entityManager->getRepository(User::class)->findAll();
foreach ($users as $user) {
$user->setPassword($hasher->hashPassword($user, $user->getPassword()));
}
$entityManager->flush();
config/packages/security.yaml:
security:
encoders:
App\Entity\User:
algorithm: scrypt
cost: 15 # CPU/memory cost (default: 15)
time: 2 # CPU cost (default: 2)
block_size: 8 # Block size (default: 8)
Performance Impact
cost: 15, time: 2) are secure but may slow down registration/login. Adjust based on your server’s capabilities.Legacy Symfony Versions
security.yml (not security.yaml).Usu\ScryptPasswordEncoderBundle\Encoder\ScryptEncoder is properly registered as a service.Password Reset Tokens
hash_hmac). Scrypt is overkill for short-lived tokens.Database Schema
password column is TEXT or VARCHAR(255) (scrypt hashes are long).Invalid Hashes: If isPasswordValid() fails, verify:
salt (if manually managed) is correct. Scrypt auto-generates salts in Symfony 5+.Logs: Enable Symfony’s debug mode to inspect the encoder:
APP_DEBUG=1 php bin/console debug:container usu_scrypt_password_encoder
Custom Encoder
Extend Usu\ScryptPasswordEncoderBundle\Encoder\ScryptEncoder to modify behavior (e.g., dynamic cost based on user role):
class CustomScryptEncoder extends ScryptEncoder {
protected function getParameters(UserInterface $user) {
$params = parent::getParameters($user);
$params['cost'] = $user->isAdmin() ? 18 : 15;
return $params;
}
}
Register it as a service, replacing the default encoder.
Event Listeners
Use Symfony’s PasswordReset events to log or validate scrypt hashes:
// config/services.yaml
services:
App\EventListener\ScryptListener:
tags:
- { name: 'kernel.event_listener', event: 'security.password_reset.start', method: 'onPasswordReset' }
Fallback Encoder
Combine with Symfony’s chain_encoders for backward compatibility:
security:
encoders:
App\Entity\User:
- 'scrypt'
- 'bcrypt' # Fallback for legacy hashes
How can I help you explore Laravel packages today?