Password Hashing vs Encryption Explained
They both scramble data, but only one of them is ever the right choice for storing a password. Here's the real difference, and why it matters.
The Core Distinction: Reversible vs One-Way
Encryption is designed to be reversed. Data goes in, a transformation happens using a key, and anyone holding the correct key can run the process backward to recover the original data exactly. This reversibility is the entire point β encryption exists so that authorized parties can get the original information back when they need it, while unauthorized parties without the key cannot.
Hashing is designed specifically not to be reversed. A hash function takes input of any size and produces a fixed-length output, and that process is deliberately one-directional β there is no key that converts a hash back into the original input, by design. Two different inputs should (with overwhelming probability) never produce the same hash output, and even a tiny change to the input produces a completely different hash, but going from the hash back to the input is intended to be computationally infeasible.
How Encryption Actually Works: Symmetric and Asymmetric
Symmetric encryption (AES being the dominant modern standard) uses the same key to both encrypt and decrypt data. It's fast and efficient, which makes it the right choice for encrypting large amounts of data β a database column, a file, an entire disk β but it requires securely sharing that single key with anyone who needs to decrypt the data, which becomes the hard problem in any system using it at scale.
Asymmetric encryption (RSA and elliptic-curve methods like ECDSA being common examples) uses a mathematically linked key pair: a public key that can encrypt data, and a separate private key required to decrypt it. This solves the key-distribution problem symmetric encryption struggles with β you can publish your public key openly, and only your private key can decrypt what was encrypted with it β but asymmetric operations are computationally far more expensive, so in practice most real systems (including TLS, the protocol securing HTTPS) use asymmetric encryption briefly to securely exchange a symmetric key, then switch to fast symmetric encryption for the actual data.
How Hashing Actually Works
A cryptographic hash function processes input through a fixed algorithm and produces a digest of consistent length regardless of input size β hashing a single character or an entire book through SHA-256 both produce a 256-bit output. Three properties define a cryptographically useful hash function: it must be deterministic (the same input always produces the same output), it must exhibit the avalanche effect (a tiny input change produces a drastically different output), and it must be computationally infeasible to find two different inputs producing the same output (collision resistance).
General-purpose hash functions like SHA-256 are deliberately built to be fast, because they're used for tasks like verifying file integrity or generating unique identifiers, where speed is a feature. This same speed becomes a liability the moment you use a general-purpose fast hash for password storage β which is precisely why password-specific hashing algorithms exist and behave very differently, covered later in this guide.
Why Passwords Are Hashed, Never Encrypted
A properly built authentication system never needs to recover a user's original password β it only ever needs to verify that the password entered at login matches the one set at account creation. That verification-only requirement is exactly what one-way hashing provides: store the hash, and when someone logs in, hash their entered password using the same algorithm and compare the two hash outputs. Neither the service nor an attacker who steals the hash database ever has direct access to the original password.
If a service instead encrypted passwords (reversible by design), it would necessarily be holding a key somewhere capable of decrypting every user's password back to plaintext. That key becomes an enormous single point of failure: anyone who compromises it β an attacker, a rogue insider, a subpoena the company can't legally refuse β can recover every user's actual password at once. This is why any service found to be storing passwords in a reversible, encrypted (or worse, plaintext) form is considered to have a serious security failure, regardless of how strong the encryption algorithm itself is.
| Property | Encryption | Hashing |
|---|---|---|
| Reversible? | Yes, with the correct key | No, by design |
| Primary purpose | Protect data you need to retrieve later | Verify data without ever storing the original |
| Used for passwords? | No β never for stored login credentials | Yes β the correct method for password storage |
| Output length | Varies with input length | Fixed length regardless of input size |
| Common algorithms | AES (symmetric), RSA/ECC (asymmetric) | bcrypt, scrypt, Argon2 (password-specific) |
| Speed design goal | Fast, for practical data transfer | Deliberately slow, for password hashing specifically |
| Key required? | Yes β encryption and decryption keys | No key β only an optional salt/pepper |
Common Password Hashing Algorithms: bcrypt, scrypt, and Argon2
Modern password hashing uses algorithms specifically engineered to be slow and computationally expensive β the opposite design goal of a general-purpose hash function. bcrypt, dating to 1999, remains widely used and includes a configurable "cost factor" that can be increased over time as hardware gets faster, keeping the computational burden on an attacker consistently high. scrypt goes further by also demanding significant memory during computation, specifically to blunt the advantage of GPU and ASIC-based cracking hardware, which excels at raw computation but has comparatively limited fast memory per parallel unit.
Argon2, the winner of the 2015 Password Hashing Competition, is now widely considered the current best-practice choice, with configurable memory, time, and parallelism costs that let an implementer tune the algorithm's expense precisely to their threat model and hardware budget. All three deliberately sacrifice raw speed β the exact property SHA-256 and MD5 optimize for β because that speed is the attacker's primary advantage in an offline brute-force attempt against a stolen hash database.
Why Fast General-Purpose Hashes Fail for Password Storage
Using SHA-256 or, worse, the now-broken MD5 or SHA-1 algorithms to hash passwords remains a distressingly common mistake, precisely because these functions are genuinely excellent hash functions β just for the wrong job. Their speed, a virtue for file integrity checks, becomes a severe weakness for password storage: modern GPU hardware can compute billions of SHA-256 hashes per second, meaning an attacker with a stolen hash database can attempt billions of password guesses per second per device, making even a reasonably long password crackable in a practical timeframe.
A password hashed with bcrypt or Argon2, by contrast, might only allow an attacker a few hundred or few thousand guesses per second on the same hardware, because the algorithm itself is deliberately expensive to compute even once. That difference β billions of guesses per second versus a few thousand β is often the entire practical difference between a breach that exposes usable passwords within hours and one where cracking even weak passwords takes years.
Salting and Peppering: Defending Against Precomputation
A salt is a unique, random value generated per password and stored alongside its hash (unencrypted, since it doesn't need to be secret). Its purpose is to guarantee that two users with an identical password produce completely different stored hashes, which defeats rainbow table attacks β precomputed lookup tables mapping common passwords to their hash values. Without a salt, an attacker who precomputed hashes for the million most common passwords could instantly identify any matching account in a breached database; with a unique salt per user, that precomputed table becomes useless, forcing the attacker back to cracking each password individually.
A pepper is a related but distinct concept: a single secret value, shared across all password hashes in a system and stored separately from the database (often in application code or a hardware security module), added to every password before hashing. Unlike a salt, a pepper's value must remain secret to provide value β if an attacker obtains both the hash database and the pepper, it offers no additional protection. Peppering is less universally adopted than salting, but provides meaningful defense-in-depth specifically against the scenario where the hash database itself, but not the application's secrets, has leaked.
What Happens When a Hashed Password Database Actually Leaks
A breach exposing a properly salted, Argon2-or-bcrypt-hashed password database is a serious incident, but a meaningfully less catastrophic one than a breach exposing plaintext or reversibly-encrypted passwords. Attackers obtain only hash values and per-user salts β they must still perform the slow, expensive cracking process against each one individually, and a genuinely strong, unique password (the kind our password creation guide walks through building) can remain impractical to crack even with unlimited time against a properly-hashed database.
This is precisely why changing your password after a breach notification remains worthwhile even when a service claims "properly hashed and salted" β the hashing slows an attacker down significantly, but doesn't make cracking a weak password impossible, only impractical for a strong one. It also explains why services increasingly recommend immediate rotation for any account where the SAME password was reused elsewhere, since credential stuffing against other services doesn't require cracking anything at all if the original plaintext password is ever recovered by any means.
Common Misconceptions Developers and Users Both Have
A frequent misunderstanding: assuming that because a hash "looks encrypted" (a long string of random-looking characters), the two processes must be interchangeable or that hashing is simply "encryption you can't undo." They're built on entirely different mathematical foundations serving entirely different purposes, and conflating them leads directly to the specific implementation mistakes covered throughout this guide β using a reversible method where irreversibility was the actual requirement, or vice versa.
Another common misconception: believing that adding more hashing rounds with a fast algorithm (hashing a password through SHA-256 a thousand times in a row) provides comparable protection to a proper password-hashing algorithm like bcrypt. While iterated fast hashing does slow down an attacker somewhat, it lacks the memory-hardness and tunable cost parameters that make purpose-built algorithms like Argon2 specifically resistant to modern GPU and ASIC-based cracking hardware β it's a meaningfully weaker substitute, not an equivalent alternative.
A related misconception treats "hashed" as automatically meaning "safe," without checking which specific algorithm was actually used. A password hashed with unsalted MD5 technically satisfies the literal claim "your password was hashed, not stored in plaintext," while still offering only marginally better real-world protection than plaintext storage against a well-resourced attacker with modern GPU hardware. The algorithm choice and the presence of a proper unique salt matter as much as the fact that hashing happened at all.
Real Scenarios Developers and Users Actually Face
Scenario 1 β Building a signup form's backend: A developer needs to decide how to store new user passwords. The correct choice is a well-maintained bcrypt or Argon2 library, never a hand-rolled hashing scheme or a symmetric-encryption function, regardless of how convenient the latter might seem for a quick prototype.
Scenario 2 β Storing third-party API keys in an application: Unlike passwords, API keys sometimes genuinely need to be retrieved later (to make an outgoing request on the user's behalf), which makes this a legitimate case for encryption, not hashing β the exact opposite conclusion from the password-storage scenario above, despite both looking like "sensitive credential storage" at first glance.
Scenario 3 β Verifying a login attempt: When a user submits a password at login, the correct flow hashes the submitted password using the same algorithm and parameters used at signup, then compares the two hash outputs using a timing-safe comparison function β never by decrypting a stored value back to plaintext for comparison, since that would require the password to have been stored reversibly in the first place.
Scenario 4 β Receiving a breach notification from a service you use: The notification states passwords were "hashed and salted using bcrypt." This is meaningfully reassuring compared to a notification mentioning "encrypted" passwords or making no mention of hashing at all β though changing your password on that service, and anywhere else you reused it, remains the responsible next step regardless of how the breach is described.
FAQ
ToolsNovaHub guides are researched against primary sources (RFCs, vendor docs) and kept up to date as standards change. Spotted an error? Let us know.
π Related Tools & Guides Comparison
| Resource | Type | Link |
|---|---|---|
| Password Generator | Tool | Open Tool β |
| SSL Certificate Checker | Tool | Open Tool β |
| What Is SSL/TLS? | Guide | Read Guide β |
| Password Strength & Creation Guide | Guide | Read Guide β |
| Common Password Attacks & Risks | Guide | Read Guide β |