php-standard-library/hash
Hash utilities for PHP: cryptographic and non-cryptographic hashing via an Algorithm enum, HMAC helpers, and timing-safe string comparison. Lightweight package from PHP Standard Library for consistent, secure hashing across projects.
Installation:
composer require php-standard-library/hash
Add to composer.json under require or require-dev based on use case.
First Use Case: Generate a SHA-256 hash for a file checksum:
use PhpStandardLibrary\Hash\HashGenerator;
use PhpStandardLibrary\Hash\Algorithm;
$generator = new HashGenerator();
$fileContent = file_get_contents('example.txt');
$hash = $generator->generate($fileContent, Algorithm::SHA256);
Where to Look First:
src/HashGenerator.php for core functionality.src/Algorithm.php for supported algorithms (e.g., SHA256, MD5, BCRYPT).Hash Generation:
$generator = new HashGenerator();
$hash = $generator->generate('sensitive_data', Algorithm::SHA256);
Timing-Safe Comparison (Critical for security):
use PhpStandardLibrary\Hash\HashComparator;
$comparator = new HashComparator();
$isMatch = $comparator->equals($storedHash, $inputHash);
HMAC Generation (For API signatures):
$hmac = $generator->generateHmac('secret_key', 'data', Algorithm::SHA256);
Algorithm Enums:
Prefer Algorithm::SHA256 over strings for type safety and IDE autocompletion.
File Integrity Checks:
$fileHash = $generator->generate(file_get_contents($filePath), Algorithm::SHA512);
cache()->put("file_{$filePath}_hash", $fileHash, now()->addHours(1));
API Request Signing:
$signature = $generator->generateHmac(
config('app.api_secret'),
$request->getContent(),
Algorithm::HMAC_SHA256
);
Password Verification (Use Laravel’s Hash facade instead):
// Avoid: Use Hash::check() for passwords
$isMatch = $comparator->equals(
Hash::make($password),
$storedPassword
);
Laravel Service Provider: Bind the generator to the container for dependency injection:
$this->app->singleton(HashGenerator::class, function () {
return new HashGenerator();
});
Usage in controllers:
public function __construct(private HashGenerator $hash) {}
Configuration:
Define default algorithms in config/hash.php:
return [
'default_algorithm' => Algorithm::SHA256,
'hmac_key' => env('HMAC_SECRET'),
];
Testing:
Mock HashGenerator in unit tests:
$mockGenerator = Mockery::mock(HashGenerator::class);
$mockGenerator->shouldReceive('generate')
->once()
->with('test', Algorithm::MD5)
->andReturn('d41d8cd98f00b204e9800998ecf8427e');
Artisan Commands: Use for bulk operations (e.g., regenerating cache keys):
use Illuminate\Console\Command;
use PhpStandardLibrary\Hash\HashGenerator;
class RegenerateHashes extends Command
{
protected $signature = 'hashes:regenerate';
public function handle(HashGenerator $hash)
{
$data = Model::all();
foreach ($data as $item) {
$item->hash = $hash->generate($item->content, Algorithm::SHA256);
$item->save();
}
}
}
Algorithm Confusion:
Algorithm::MD5 or Algorithm::SHA1 for security-sensitive data (e.g., tokens, passwords).SHA256, BCRYPT) for sensitive data. Use non-cryptographic ones (e.g., CRC32) only for non-security purposes like checksums.Timing Attacks:
HashComparator for sensitive comparisons (e.g., API keys, session tokens).HashComparator::equals() instead of === or ==:
// UNSAFE
if ($storedHash === $inputHash) { ... }
// SAFE
if ($comparator->equals($storedHash, $inputHash)) { ... }
HMAC Misuse:
.env and regenerate them periodically:
$hmac = $generator->generateHmac(
env('API_HMAC_SECRET'),
$request->getContent(),
Algorithm::HMAC_SHA256
);
Input Handling:
generate().$hash = $generator->generate(json_encode($arrayData), Algorithm::SHA256);
Laravel Facade Overlap:
Hash facade for passwords.php-standard-library/hash only for non-password data. Passwords must use Laravel’s Hash facade.Hash Mismatches:
$rawInput = json_encode($data, JSON_UNESCAPED_UNICODE);
$hash = $generator->generate($rawInput, Algorithm::SHA256);
Performance Bottlenecks:
$start = microtime(true);
foreach ($files as $file) {
$generator->generate(file_get_contents($file), Algorithm::SHA512);
}
$time = microtime(true) - $start;
Algorithm Support:
Algorithm.php. If missing, consider:
hash() functions as a fallback.Algorithm Enums:
Algorithm::SHA256, not Algorithm::sha256.HMAC Defaults:
// UNSAFE (no secret provided)
$generator->generateHmac('data');
// SAFE
$generator->generateHmac(env('HMAC_SECRET'), 'data', Algorithm::HMAC_SHA256);
Resource Inputs:
resource) may not work as expected. Read content first:
$fileContent = file_get_contents($filePath);
$hash = $generator->generate($fileContent, Algorithm::SHA256);
Custom Algorithms:
Algorithm enum to add support for missing algorithms (e.g., BLAKE3):
namespace App\Extensions;
use PhpStandardLibrary\Hash\Algorithm;
class CustomAlgorithm extends Algorithm
{
public const BLAKE3 = 'blake3';
}
Custom Comparators:
HashComparator to add logging or additional checks:
class LoggingHashComparator implements ComparatorInterface
{
public function equals(string $hash1, string $hash2): bool
{
\Log::debug("Comparing hashes: {$hash1} vs {$hash2}");
return $comparator->equals($hash1, $hash2);
}
}
Laravel Facade Wrapper:
Hash:
// app/Facades/StandardHash.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class StandardHash extends Facade
{
protected static function getFacadeAccessor()
{
return 'hash.standard';
}
}
How can I help you explore Laravel packages today?