BaseToolbox Logo

BaseToolbox

Blog

© 2025 基础工具箱。保留所有权利。

隐私政策关于联系我们

Password Hashing Is Not What You Think It Is

Published on December 19, 2025

Last month, I reviewed a codebase where passwords were "hashed" using SHA-256. The developer was proud of using a "modern" algorithm instead of the "outdated" MD5. They didn't understand why I immediately flagged it as a security vulnerability.

Here's the thing: SHA-256 is an excellent cryptographic hash function. It's also a terrible choice for password storage. These two statements aren't contradictory—they just reflect different threat models.

Hashing vs. Encryption: The Fundamental Difference

Encryption is reversible. You encrypt data with a key, and later decrypt it with the same (or related) key. The whole point is recovering the original data.

Hashing is one-way. You feed data in, get a fixed-size output, and there's no algorithm to reverse the process. Even a tiny change in input produces completely different output.

This is why hashing works for password verification: you don't need to know the password, just whether the user's input produces the same hash as what's stored. An attacker who steals your database gets hashes, not passwords.

In theory.

Why Fast Hashes Are Dangerous

SHA-256 processes data at about 300 megabytes per second on a modern CPU. Sounds fast, right? That's the problem.

If I have a stolen database of SHA-256 password hashes, I can try billions of password guesses per second. Common passwords like "password123" or "qwerty" fall in milliseconds. Even complex passwords can be cracked by renting cloud GPU instances for a few hours.

This is why password hashing needs intentionally slow algorithms. bcrypt, scrypt, and Argon2 are designed to be computationally expensive. They include adjustable "work factors" that let you increase difficulty as hardware gets faster.

With bcrypt at a typical work factor of 12, the same attack that would test billions of SHA-256 guesses per second might manage only a few hundred bcrypt guesses. That's the difference between "cracked in seconds" and "cracked in centuries."

When Each Algorithm Makes Sense

MD5 and SHA-1: Don't use for security. Both have known collision attacks. MD5 can still be useful for non-security purposes—checksums for file integrity, hash table keys, deduplication—but never for passwords or signatures.

SHA-256 and SHA-3: Data integrity and signatures. These are current best practices for verifying file integrity, digital signatures, and anywhere you need a cryptographic hash. Fast and secure against collision attacks.

bcrypt, scrypt, Argon2: Password storage. Specifically designed for hashing secrets where brute-force resistance matters. Use one of these for any password or sensitive credential you store.

Salt: Why It Matters

A "rainbow table" is a precomputed database of hashes for common passwords. Without salting, the same password always produces the same hash. If two users have the password "letmein," their hashes are identical—and if one is cracked, both are cracked.

Salt is random data added to each password before hashing. Even identical passwords produce different hashes, making precomputed attacks useless.

Modern password hashing functions like bcrypt include salting automatically. If you're implementing password storage manually (which you probably shouldn't be), always generate a unique salt for each password.

Checksums: The Legitimate Use for Fast Hashes

Not every hash is about security. Sometimes you just need to detect changes or verify integrity.

Downloading a file and want to verify it wasn't corrupted? Compare SHA-256 checksums. This isn't protecting against an attacker—it's catching transmission errors.

Deduplicating files in storage? MD5 is actually fine. You're not worried about someone crafting malicious collisions, just identifying identical files.

Building a cache key from request parameters? CRC32 or MurmurHash might be more appropriate than a cryptographic hash.

The Takeaway

The word "hash" covers algorithms with very different properties and use cases. Using SHA-256 for passwords is wrong not because SHA-256 is bad, but because it's the wrong tool. Using bcrypt for checksums would be wastefully slow.

Match the algorithm to the threat model. For password storage, use purpose-built password hashing. For data integrity, use standard cryptographic hashes. For non-security uses, use whatever's fast and convenient.

And whenever you're unsure, use a well-tested library that makes these decisions for you. Password storage especially has subtle pitfalls that trip up even experienced developers.

Ready to try it yourself?

Put what you've learned into practice with our free online tool.

Generate Hashes