php-standard-library/hash
Cryptographic and non-cryptographic hashing for PHP with an Algorithm enum, timing-safe comparison, and HMAC support.
md5() for cache keys, sha1() for file checksums, hash_hmac('sha256', ...) inline for webhook signatures, and Hash::make() for passwords. This package gives one typed API (Algorithm enum, HMAC, timing-safe comparison) for everything except passwords. The decision it unlocks: adopt a single team-wide convention for non-password hashing and lint against ad-hoc calls.hash_equals semantics) is the kind of fix that never wins a sprint priority fight but removes a real side-channel class of bug. Bundling it into a "standardize hashing" ticket gives you a security win with a small, contained diff surface.hash()/hash_hmac() that prevents engineers from choosing algorithms ad hoc. Estimated adoption effort is low (composer require + replace call sites), so the decision is cheap to reverse; the real cost is the internal convention and code review discipline, not the dependency.password_hash/Hash for actual credentials).Hash facade owns passwords; this package owns everything else. Without that, the ticket becomes a turf war with the framework and adoption stalls.Consider adopting when:
== or strcmp, or md5()/sha1() still in production paths.Look elsewhere — or wait — when:
Hash facade (bcrypt/argon2id) is more mature, better integrated, and has rehashing/needsRehash semantics this package does not aim to replace. Do not swap it.ext-hash exposes, no BLAKE3. If a product requirement names an algorithm, verify support before committing.hash() before mandating it on a hot path.hash_hmac('sha256', $payload, $secret) in two places, adding a dependency is worse than a two-line internal helper. The package pays off at breadth, not depth.Net PM read: worth a scoped pilot behind an internal adapter; not worth a mandated org-wide dependency today. The wrapper is what de-risks it — the wrapper is also the deliverable that survives if the package doesn't.
To executives (30 seconds): We hash data in a dozen inconsistent ways across the codebase, and some of those comparisons are theoretically attackable. This is a small, free, MIT-licensed library that gives us one consistent, safer way to do every hashing job except passwords. The cost is roughly a sprint-week of engineering plus review; the upside is a cleaner security posture, an easier audit, and the plumbing for webhook signing and privacy-safe logging we already have on the roadmap. The risk is that the library is young and has no visible user base — so we're wrapping it in our own thin interface and piloting it on low-stakes work first. Worst case, we swap the internals and keep the interface.
To engineering leads (the ask): Adopt it behind an internal service/adapter with one rule — Hash facade for passwords, this for everything else. Start with file checksums and audit-log pseudonymization. Add unit tests for every algorithm we permit, explicit tests for timing-safe comparison and binary/empty-string inputs, and static analysis to flag new md5()/sha1() usage. Pin the version, track the parent repo's releases, and confirm PHP version compatibility. Do not mandate it on any hot path until we have benchmark numbers against native hash().
Why now, and what we're explicitly not doing: Now because the code is being touched anyway and the marginal cost is lowest; the enum-based API is a real improvement over passing algorithm strings around. Not doing — replacing Laravel's password hashing, betting on exotic algorithms, or making this a hard org-wide requirement on day one. Success criteria for the pilot: zero call sites left with non-timing-safe token comparison, one documented convention in the runbook, and a verified rollback path. If the package goes quiet, we own the adapter and the migration back to native functions is a day of work, not a quarter.
How can I help you explore Laravel packages today?