PHP
Token Bucket
Allow a short burst, then refill tokens at a steady rate. The burst cannot exceed the bucket size.
Store a password as a salted hash, with a pepper from app config. This is not reversible encryption.
final class PasswordHasher
{
public function __construct(
private readonly string $pepper,
private readonly string $algo = PASSWORD_DEFAULT,
private readonly array $options = [],
) {
if ($this->pepper === '') {
throw new InvalidArgumentException('Pepper must not be empty.');
}
}
public function hash(string $password): string
{
if ($password === '') {
throw new InvalidArgumentException('Password must not be empty.');
}
$hash = password_hash($this->season($password), $this->algo, $this->options);
if ($hash === false) {
throw new RuntimeException('Could not hash the password.');
}
return $hash;
}
public function verify(string $password, string $hash): bool
{
if ($password === '' || $hash === '' || ! str_starts_with($hash, '$')) {
return false;
}
return password_verify($this->season($password), $hash);
}
public function needsRehash(string $hash): bool
{
return password_needs_rehash($hash, $this->algo, $this->options);
}
private function season(string $password): string
{
return hash_hmac('sha256', $password, $this->pepper, true);
}
}
$hasher = new PasswordHasher($_ENV['APP_PEPPER'] ?? '');
$hash = $hasher->hash($password);
if (! $hasher->verify($password, $hash)) {
throw new RuntimeException('Invalid password.');
}
if ($hasher->needsRehash($hash)) {
$user->password = $hasher->hash($password);
}
A practical place for this snippet in a real project.
Useful for storing a user password and checking it at login. It is not for encrypting files or API tokens.
Allow a short burst, then refill tokens at a steady rate. The burst cannot exceed the bucket size.
Reuse an idle connection inside the same process, instead of opening a new one for every query.
Describe the problem or idea, and I will see if it belongs in the library.