The idea: a lock vs a fingerprint
Encryption is a lock. It scrambles a message with a key, and the same key (or its partner key) unscrambles it. Nothing is lost: the ciphertext holds the whole message. Hashing is a fingerprint. A hash function turns any input into a short, fixed-size digest. There is no key, and there is no way back: the digest identifies the message but does not contain it.
The canvas runs both on the same message. The left lane encrypts with a tiny cipher so every letter can be checked by hand; the right lane computes real SHA-256, so you can check every digest with printf 'MEET AT NINE' | shasum -a 256. The band at the bottom shows the two jobs people mix up: checking a download and storing passwords.
Encryption: secret, and reversible with the key
The page's cipher shifts each letter forward by the matching letter of the key LEMON (A = 0, B = 1, … Z = 25), repeating the key; spaces stay as they are. M + L = X, E + E = I, E + M = Q, so MEET AT NINE becomes XIQH NE RUBR. Decrypting shifts back by the same key. This is the Vigenère cipher, which is broken; real systems use AES-GCM or ChaCha20-Poly1305, but the shape is the same: key in, ciphertext out, same key back (Demo: same message, two lanes).
- The ciphertext is as long as the message (real ciphers add a few bytes: a nonce and a tag). Demo: short vs long message: 5 letters give 5, 28 letters give 28.
- The secret is the key, not the method. With the wrong key
APPLE,XIQH NE RUBRdecrypts toXTBW JE CFQN(Demo: decrypt with the wrong key). - With one shared key both sides lock and unlock (symmetric); with a key pair, the public key locks and only the private key unlocks (asymmetric). See Symmetric vs Asymmetric Encryption.
Hashing: a fixed-size fingerprint
SHA-256 pads the input to a multiple of 64 bytes and mixes each block through 64 rounds of additions, rotations and XORs. The result is always 256 bits, written as 64 hex digits, whether the input is 6 bytes or 5 GB. Three properties make it useful:
- Deterministic: the same input gives the same digest on every computer, every time. No key, no randomness.
- One-way (preimage resistant): from a digest you cannot compute an input. The only way is to guess inputs and hash each guess.
- Collision resistant: you cannot find two inputs with the same digest. Collisions must exist (infinitely many inputs, 2256 digests), but finding one takes about 2128 tries.
A good hash also has the avalanche effect: change one input bit and about half of the output bits flip. MEET AT NINE hashes to 89c16b2f…, MEET AT NINF to 17757cbb…: 136 of the 256 bits differ (Demo: change one letter). The toy cipher changed just one letter. Real ciphers hide that too, because a fresh random nonce makes every encryption of the same message different, but they still keep all of it.
MD5 and SHA-1 are broken for collisions and must not be used for security. SHA-256, SHA-3 and BLAKE2/BLAKE3 are current choices.
Side by side
| Encryption | Hashing | |
|---|---|---|
| Direction | Two-way: decrypt gives the message back | One-way: no way back |
| Key | Needed; it is the secret | None; anyone can compute it |
| Output size | Grows with the message | Fixed (SHA-256: 32 bytes) |
| Same input twice | Different output (fresh nonce) | Same digest |
| Gives | Confidentiality: only key holders read it | Integrity / identity: did it change? is it the same? |
| "Breaking" it means | Getting the key | Guessing the input, or finding a collision |
| Examples | AES-GCM, ChaCha20-Poly1305, RSA-OAEP | SHA-256, SHA-3, BLAKE3; for passwords bcrypt, Argon2id |
Neither is encoding. Base64 or hex just rewrites bytes in another alphabet, with no key and no secret: anyone can decode it. See Base64 Encoding & Decoding.
Integrity: checksums, HMAC and signatures
Encryption alone does not notice changes. In Demo: tampering, Eve turns the last ciphertext letter R into S and the receiver decrypts MEET AT NINF with no error. AES-GCM and ChaCha20-Poly1305 add an authentication tag for exactly this reason: a changed byte makes decryption fail.
A hash catches the change when the digest comes from somewhere the attacker can't touch: you download a file, hash it and compare with the checksum on the publisher's site. 17757cbb… is not 89c16b2f…, so the file is rejected. But if Eve can also change the published checksum, she just hashes her own file and posts that digest: the check passes. To stop that you need a key: an HMAC (a hash mixed with a shared secret key, RFC 2104) or a digital signature (the publisher's private key signs the hash).
Passwords: hash with salt, slowly
A server needs to check a password, never to read it back, so it should store a hash, not a ciphertext. If passwords are encrypted, the key has to be on the server to check logins, and a breach that copies the database usually copies the key too: every password is read at once, strong ones included (Demo: password leak, encrypted). Equal passwords also show up as equal ciphertexts: alice and carol both store DYZGUTRQ.
With hashes, the server stores SHA-256(salt + password) and, at login, hashes what the user typed with the same salt and compares. After a breach the attacker can only guess. The salt is a random value stored next to each hash: alice (a1f3) and carol (7c02) both use SUNSHINE but store 8ae4de09d373… and aef966d27f10…, so cracking one does not crack the other, and precomputed tables are useless (Demo: password leak, salted hash: 5 + 6 + 5 = 16 guesses for three users).
Salt does not save a weak password: SUNSHINE is in every wordlist. What helps is a slow password hash. A GPU computes billions of SHA-256 hashes per second but only thousands of bcrypt hashes. The OWASP Password Storage Cheat Sheet recommends Argon2id (19 MiB of memory, 2 iterations, 1 thread), or scrypt, bcrypt with a cost of at least 10, or PBKDF2-HMAC-SHA256 with 600 000 iterations. See Salt vs Pepper for a secret pepper added on top, and OWASP Cryptographic Failures for the mistakes in practice.
Which one do I need?
- Someone must read the data later (a message, a backup, a credit-card number you charge again): encrypt, and protect the key.
- You only need to recognise or compare the data (passwords, file checksums, deduplication, cache keys, commit IDs): hash.
- You need to prove the data wasn't changed by someone who might also change the checksum: HMAC or a signature, or encrypt with an AEAD cipher.
See also: A CRC also turns data into a short fixed-size value, but it is not a cryptographic hash: it is linear and has no key, so anyone can change the data and fix the CRC (see Cyclic Redundancy Check (CRC)).
See Inside AES-128 and SHA-256 for the rounds step by step.
An n-bit hash gives only n/2 bits of collision resistance because of the birthday paradox.
Content-addressed IDs in practice: a git commit's ID is the hash of its tree, parents and dates, so a rebased copy gets a new one — see Git Merge vs Rebase.
Git names every file, directory and commit by its SHA-1 hash: see Git objects.
Hashes chained into a tree let one value commit to many: see Bitcoin Merkle Trees and SPV Proofs.
Why slowly, and how slow, is shown on Password Hashing: Fast vs Slow Hashes (SHA-256 vs bcrypt, scrypt and Argon2id on a GPU).
What the page leaves out
How AES and the SHA-256 rounds work inside; nonces, IVs and cipher modes; key management and key derivation; length-extension attacks on plain SHA-256 (the reason HMAC exists instead of SHA-256(key + message)); peppers; exact attacker speeds, which depend on hardware; and quantum computers, which would halve the effective security of hashes and symmetric keys (Grover) and break RSA and elliptic curves (Shor).