MD5, SHA-1, and plain SHA-256 are designed to be fast, which is exactly what you do not want for passwords. If your database leaks, an attacker can try billions of guesses per second against those hashes and recover most passwords quickly. Use a slow, salted password hash built for the job, like bcrypt or argon2.
Why it's a problem
Fast general-purpose hashes make offline cracking cheap, so a stolen users table with MD5 or SHA-1 hashes is effectively a list of plaintext passwords within hours. Purpose-built password hashes are deliberately slow and salted per user, which makes mass cracking impractical even after a breach.
The pattern
// far too fast, and unsalted
const hash = crypto.createHash("md5").update(password).digest("hex");The fix
import bcrypt from "bcrypt"; // hash on signup (bcrypt salts automatically) const hash = await bcrypt.hash(password, 12); // verify on login const ok = await bcrypt.compare(password, hash);
Why AI tools write this
createHash('md5') is a short, familiar line that produces a hash, so when the task is 'hash the password' it is a common completion, especially since MD5 examples are everywhere in training data. It runs and stores a hash; nothing signals that the hash is unsafe for passwords.
The quick fix
- Hash passwords with bcrypt, scrypt, or argon2, never MD5, SHA-1, or plain SHA-256.
- Let the library handle salting; do not roll your own.
- On your next login for each user, re-hash with the strong algorithm and migrate.
Common questions
Is SHA-256 safe for password hashing?
No. SHA-256 is a general-purpose hash designed to be fast, which makes offline cracking with a GPU practical. Use bcrypt, argon2, or scrypt, which are designed to be slow and are the right tools for passwords.
What cost factor should I use for bcrypt?
12 is the commonly recommended starting point, with 10 as the minimum acceptable. Measure how many rounds your hardware can compute in under 250ms per hash and set accordingly.
I am migrating from MD5 to bcrypt. Do existing passwords need to be invalidated?
You cannot rehash stored MD5 hashes without knowing the original passwords. The standard approach is to rehash with bcrypt on the user's next successful login, replacing the old hash at that point.