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.

Top: MEET AT NINE is encrypted with key LEMON into XIQH NE RUBR, and decrypting with LEMON gives MEET AT NINE again. Bottom: MEET AT NINE goes through SHA-256 into the 64-hex-digit digest 89c16b2f..., and the arrow back to the message is crossed out.
Encryption is two-way and needs a key; hashing is one-way, has no key and always gives the same size.

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 RUBR decrypts to XTBW 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

EncryptionHashing
DirectionTwo-way: decrypt gives the message backOne-way: no way back
KeyNeeded; it is the secretNone; anyone can compute it
Output sizeGrows with the messageFixed (SHA-256: 32 bytes)
Same input twiceDifferent output (fresh nonce)Same digest
GivesConfidentiality: only key holders read itIntegrity / identity: did it change? is it the same?
"Breaking" it meansGetting the keyGuessing the input, or finding a collision
ExamplesAES-GCM, ChaCha20-Poly1305, RSA-OAEPSHA-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).

Left panel, plain hash: Eve changes the file to MEET AT NINF and replaces the published digest with 17757cbb, so the receiver's check matches and the changed file is accepted, marked with a cross. Right panel, HMAC with a secret key K: Eve changes the file but cannot compute the tag without K, so the receiver's tag does not match and the file is rejected, marked with a tick.
A plain hash only proves "matches this digest"; add a secret key (HMAC) or a signature and the attacker can no longer make a matching one.

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.

Left panel, encrypted passwords: the users table and the key file LEMON leak together, and the attacker decrypts SUNSHINE, SUNSHINE and LETMEIN in three steps, marked with a cross. Right panel, salted slow hashes: the attacker has only salts and hashes and must guess each user separately, and each bcrypt guess is slow, marked with a tick.
Encrypted passwords fall all at once with the key; salted slow hashes force the attacker to guess, user by user, at a slow rate.

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).