Hashing vs Encryption: What Every Developer Must Know
Why these are different problems with different solutions — and the dangers of confusing them.
Two Tools for Two Different Problems
Hashing and encryption are both cryptographic primitives, and both transform input data into something that looks like gibberish. That is where the similarity ends. Encryption is reversible: given a ciphertext and the right key, you recover the original plaintext. Hashing is one-way: given a hash output, you cannot recover the input, and there is no key. The two solve fundamentally different problems and are not interchangeable. Storing passwords encrypted so they can be "decrypted later" is a security failure; verifying file integrity with encryption rather than a hash is nonsensical.
Every modern system uses both, in different layers, for different reasons. A developer who confuses them will eventually build a system that is either insecure (because they treated a hash like ciphertext) or unusable (because they treated ciphertext like a hash and lost the data permanently).
Hashing: Properties and Use Cases
A cryptographic hash function takes an arbitrary-length input and produces a fixed-length output called a digest or hash value. The function has three properties that distinguish it from a checksum like CRC32:
- Pre-image resistance. Given a hash output
h, it is computationally infeasible to find any inputmsuch thathash(m) = h. - Second pre-image resistance. Given an input
m1, it is infeasible to find a different inputm2such thathash(m1) = hash(m2). - Collision resistance. It is infeasible to find any two distinct inputs that hash to the same output.
The classic use cases for hashing are password storage (storing the hash, not the password, so a database leak does not directly expose credentials), file integrity verification (comparing the hash of a downloaded file to a published digest to detect corruption or tampering), content addressing (Git's object store, IPFS, and many deduplication systems use hashes as identifiers), and digital signatures (signing the hash of a message rather than the full message, for performance).
SHA-256 per NIST FIPS 180-4
The most widely used cryptographic hash in 2025 is SHA-256, specified in NIST FIPS 180-4 (August 2015). SHA-256 takes any input and produces a 256-bit (32-byte, 64-hex-character) digest. Internally, the algorithm processes the input in 512-bit (64-byte) blocks and runs each block through 64 rounds of mixing operations drawn from a small set: bitwise AND, OR, XOR, NOT, right-shifts, right-rotations, and 32-bit modular addition. The algorithm initializes eight 32-bit working variables to specific constants derived from the fractional parts of the square roots of the first eight primes, then folds each input block into those variables over the 64 rounds. After every block has been processed, the eight variables concatenated together form the 256-bit output.
The choice of constants — square roots of small primes — is not arbitrary. NIST selected them to be "nothing up my sleeve" numbers: publicly justifiable values that the algorithm's designers could not have engineered to hide a backdoor. The same design principle appears in AES's S-box (derived from multiplicative inverses in GF(2^8)) and in many other NIST standards.
SHA-256 is part of the SHA-2 family, which also includes SHA-224, SHA-384, SHA-512, SHA-512/224, and SHA-512/256. The numbers refer to digest length. The older SHA-1 (160-bit) was broken by a practical collision attack published in 2017 by Stevens et al. and is no longer safe for any security use. The even older MD5 (128-bit) has been broken since the mid-2000s. The successor SHA-3 family (FIPS 202) uses a completely different construction (sponge rather than Merkle-Damgard) and is recommended for new systems that want defense in depth against future SHA-2 breaks.
Password Hashing: A Special Case
Plain SHA-256 is the wrong tool for password storage, even though SHA-256 is a strong hash. The reason is speed: SHA-256 is fast enough for an attacker with a GPU to try billions of guesses per second against a stolen hash database. Password hashing needs to be deliberately slow.
The right tools are bcrypt (with a configurable cost factor that doubles the work per increment), scrypt (which also requires memory, making GPU attacks less efficient), or Argon2id (the winner of the 2015 Password Hashing Competition, with both memory and time costs). All three also include a per-password random salt, which prevents attackers from precomputing tables of common-password hashes and from noticing when two users share the same password.
The salt is not secret. It is stored alongside the hash, often embedded in the same string. Its purpose is to ensure that two users with the same password get different stored hashes, so an attacker who steals the database has to attack each password individually rather than looking up a single rainbow table.
Encryption: Properties and Use Cases
Encryption is reversible. Given a key k and a plaintext p, an encryption algorithm produces a ciphertext c = E(k, p), and a corresponding decryption algorithm recovers p = D(k, c). Without the key, the ciphertext is unintelligible. Encryption comes in two flavors: symmetric, where the same key is used for encryption and decryption (AES, ChaCha20), and asymmetric, where one key encrypts and a different but mathematically related key decrypts (RSA, ECDSA, Ed25519).
Classic use cases for encryption are data at rest (encrypting disk volumes, database columns, and backup files so that stolen media does not reveal plaintext), data in transit (TLS wraps every HTTP request and response in symmetric encryption negotiated via asymmetric key exchange), and end-to-end messaging (Signal, WhatsApp, and iMessage all encrypt the message body so that even the server cannot read it).
The critical difference from hashing is reversibility. If you encrypt a customer's credit card number to store it, you must keep the decryption key somewhere — and that key becomes the single most valuable asset in your infrastructure. PCI DSS mandates strict key management procedures exactly because of this asymmetry: encrypted data is only as safe as the key, and the key has to be accessible to the systems that need to decrypt.
Message Authentication: HMAC
Hashing and encryption meet in HMAC (Hash-based Message Authentication Code, RFC 2104). HMAC combines a cryptographic hash with a secret key to produce a tag that proves both integrity (the message was not modified) and authenticity (the sender knows the key). JWTs use HMAC-SHA256 for signed tokens; AWS request signing uses HMAC-SHA256; Stripe webhook signature verification uses HMAC-SHA256 with the webhook signing secret. HMAC is the right tool whenever you need to say "this message is from someone who knows the shared secret" without encrypting the message itself.
The Common Mistakes
- Storing passwords with plain SHA-256. Too fast; vulnerable to GPU brute force. Use bcrypt, scrypt, or Argon2id.
- Hashing without a salt. Identical passwords produce identical hashes; attackers can precompute rainbow tables. Always salt.
- Encrypting passwords so they can be "decrypted later." Passwords should never be recoverable; users should reset, not retrieve. If you need password-equivalent access for automated systems, use API keys or OAuth, not stored passwords.
- Using MD5 or SHA-1. Both have practical collision attacks. Use SHA-256 at minimum, or SHA-3 for new systems.
- Confusing encryption with hashing in audit logs. "We encrypt all passwords" can mean either "we hash them properly" or "we encrypt them so we can decrypt them later." The two have very different security implications; specify which.
- Rolling your own crypto. Standard library implementations of SHA-256, AES, and HMAC have been audited for years. A custom implementation almost certainly has a side-channel or correctness bug. Use the standard library.
Conclusion
Hashing proves integrity and authenticity without reversibility. Encryption proves confidentiality with reversibility. The two are not interchangeable, and the choice between them depends entirely on whether the legitimate party needs to recover the original data. For passwords, the answer is no — use a slow hash like bcrypt or Argon2id, with a per-password salt, and never store recoverable credentials. For data the system itself must use, the answer is yes — use a standard symmetric cipher like AES-256-GCM or ChaCha20-Poly1305, manage the key carefully, and rotate it. SHA-256 per NIST FIPS 180-4 remains the workhorse for integrity, signatures, and content addressing; pair it with HMAC whenever you need to prove the sender knew a secret. The primitives are well-understood; the bugs are almost always in how they are combined. Written by the HT99 Tools Editorial Team.
Try the Tool This Article Explains
Put what you've learned into practice with our free, accurate calculators.