TL;DR
Yes, a hashing function can absolutely be implemented insecurely. Simply using a standard hashing algorithm doesn’t guarantee security. Weaknesses arise from poor salt usage, slow or non-existent key stretching, predictable algorithms, and insufficient output length. This guide shows how to avoid common pitfalls.
1. Understanding Hashing Basics
Hashing takes data of any size (a password, a file) and turns it into a fixed-size string of characters. It’s one-way: you can’t easily get the original data back from the hash. Good hashing is crucial for storing passwords safely.
2. Why Standard Algorithms Aren’t Enough
Algorithms like SHA-256 and bcrypt are strong, but they need to be used correctly. Just calling hash('sha256', 'password') in PHP (for example) is usually not enough.
3. The Importance of Salting
A salt is a random string added to the password *before* hashing. This prevents attackers from using pre-computed tables of common passwords and their hashes (rainbow tables). Each user should have a unique salt.
- Generate Unique Salts: Use a cryptographically secure random number generator.
- Store Salts with Hashes: Keep the salt alongside the hash in your database.
4. Key Stretching: Slowing Down Attackers
Key stretching repeatedly hashes the password (with the salt) many times. This makes brute-force attacks much slower, even with rainbow tables.
- PBKDF2: A widely used key derivation function.
- bcrypt/Argon2: These algorithms include built-in key stretching and are generally preferred over manual implementations.
5. Algorithm Choice and Output Length
- Avoid MD5 & SHA-1: These are considered broken and should never be used for passwords.
- SHA-256 or Higher: Good choices, but *always* use with salting and key stretching.
- Output Length Matters: Longer hashes make brute-force attacks harder. bcrypt/Argon2 handle this automatically.
6. Common Mistakes to Avoid
- Using the Same Salt for All Users: Completely defeats the purpose of salting.
- Not Using a Salt at All: Extremely insecure.
- Insufficient Key Stretching: Makes brute-force attacks feasible.
- Storing Passwords in Plain Text: Never, ever do this!
7. Password Verification
When a user logs in, hash the entered password with their stored salt and compare it to the stored hash.
Important: Use password_verify() when using bcrypt/Argon2 for verification. It handles the salt and hashing internally.

