Comparing PHP Hashing Functions: `md5`, `sha1`, `hash()`, `password_hash()`, and `hash_hmac()`
A practical comparison of PHP’s hashing functions including `md5`, `sha1`, `hash()`, `password_hash()`, and `hash_hmac()` — which one should you use and why?

Foreword
In a recent project, I needed to implement a redirection mechanism that included certain GET parameters in the URL. To prevent exposing these parameters publicly and to ensure they couldn't be reverse-engineered, I decided to use HMAC hashing with a secret key.
By using hash_hmac('sha256', $decryptNeededInfo, $secret)
, where the secret is securely stored and privately shared between
applications on different domains, I was able to generate non-reversible, tamper-proof tokens. This approach provides a
robust level of security for encoding identifiers or temporary access keys — and it served as the inspiration behind
this post.
Storing Sensitive Data in PHP
Hashing is a fundamental technique in any PHP application that needs to store or verify sensitive data, such as passwords or API tokens. PHP provides several hashing functions, but not all are equally secure or suitable for the same use cases.
In this post, we’ll compare the most commonly used PHP hashing functions:
md5()
sha1()
hash()
password_hash()
hash_hmac()
1. md5() – Fast but Unsafe
$hash = md5("mypassword");
✅ Pros:
- Extremely fast
- Available in all PHP versions
❌ Cons:
- Cryptographically broken
- Easily cracked with rainbow tables or brute force
- Not recommended for password hashing
Verdict: Only use it for non-security tasks like file integrity checks or cache keys.
2. sha1() – Slightly Better, Still Weak
$hash = sha1("mypassword");
✅ Pros:
- Slightly stronger than md5
- Still fast and simple to use
❌ Cons:
- Also cryptographically broken
- Not resistant to collisions or brute force
Verdict: Like md5, sha1 is outdated for security-critical applications. Still insecure for passwords or tokens. Avoid for anything sensitive.
3. hash() – Flexible, General-Purpose Hashing
$hash = hash('sha256', "mypassword");
✅ Pros:
- Supports many modern algorithms
- Better than md5 / sha1 for general-purpose usage
- Great for hashing file contents, non-sensitive values
❌ Cons:
- No salting or cost factor
- Fast by design — not ideal for password hashing
Verdict: Use hash() for general hashing, not for passwords. For example, use hash_hmac() for token signing.
4. password_hash() – The Gold Standard for Passwords
$hash = password_hash("mypassword", PASSWORD_DEFAULT);
✅ Pros:
- Built-in salting automatically
- Supports bcrypt and Argon2
- Adjustable cost factor
- Paired with password_verify() for safe validation
- Resistant to brute-force attacks
❌ Cons:
- Slightly slower (which is actually a security feature)
- Generates a longer string (60+ characters)
Verdict: Always use password_hash() for passwords. Pair it with password_verify() to check the hash.
5. hash_hmac() – Secure and Tamper-Proof with a Secret
✅ Pros:
- Combines hashing with a secret key
- Resistant to tampering and forgery
- Great for URL tokens, APIs, and integrity checks
- Output is deterministic and consistent
❌ Cons:
- Requires secure management of the secret key
- Not suitable for password hashing
Verdict: Use for secure message authentication and token protection. Strong and reliable when paired with a secret key.
Summary Table
Function | Secure? | Use for Passwords? | Salting | Adjustable Cost | Requires Secret? | Recommended Use |
---|---|---|---|---|---|---|
md5() | ❌ No | ❌ No | ❌ No | ❌ No | ❌ No | Checksums, cache keys |
sha1() | ❌ No | ❌ No | ❌ No | ❌ No | ❌ No | Checksums, legacy support |
hash() | ⚠️ Partial | ❌ No | ⚠️ (manual) | ❌ No | ❌ No | File contents, general hashing |
password_hash() | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No | Password storage |
hash_hmac() | ✅ Yes | ❌ No | ⚠️ Manual | ❌ No | ✅ Yes | API tokens, signed URLs, HMAC validation |
⚠️
hash()
andhash_hmac()
support manual salting — you can prepend or append a salt to the input data before hashing. However, unlikepassword_hash()
, salting is not automatic, so it's your responsibility to manage it securely.
Conclusion
Choose your hashing function based on your use case:
- ✅ Use password_hash() for storing user passwords.
- ✅ Use hash_hmac() for token generation, secure redirection, and API signatures — as long as your secret key is safe.
- ⚠️ Use hash() for general hashing of content or filenames.
- 🚫 Avoid md5() and sha1() in any security-sensitive context.
Hashing is powerful — but only when used appropriately.