Hashing vs encryption vs encoding: three things people constantly confuse
Base64 is not encryption. Hashing is not reversible. Encryption needs a key. Here's the clear, correct mental model — with a worked example of each.
Almost every developer has, at some point, said one of these three words when they meant another. Someone "encrypts" a value with Base64. A code review claims a password is "hashed" when it's actually encrypted. A bug report says data was "encoded" when it should have been kept secret. These mix-ups aren't just sloppy vocabulary — they cause real security holes, because the three operations have completely different guarantees.
Here's the clean way to keep them straight. The single most useful question to ask about any transformation is: can it be reversed, and does reversing it require a secret?
- Encoding — reversible, no secret needed. Anyone can undo it.
- Encryption — reversible, but only with the right key. Without the key, it's useless.
- Hashing — not reversible at all. There's no "undo," by design.
Get that table into your head and the confusion mostly evaporates. Now let's make each one concrete.
Encoding: changing the format, keeping the meaning
Encoding transforms data from one representation into another so it can be safely stored or transmitted. It has nothing to do with security. There is no key, no secret, and anyone — including any attacker — can reverse it trivially. Its job is compatibility, not confidentiality.
The classic example is Base64. Lots of systems (email headers, JSON fields, data URLs, HTTP basic auth) can only safely carry plain text, not arbitrary binary bytes. Base64 solves this by mapping every 3 bytes of binary into 4 printable ASCII characters drawn from a 64-symbol alphabet (A-Z, a-z, 0-9, +, /). That's where the name comes from.
Worked example — encode the word Snap:
Text: S n a p
ASCII: 83 110 97 112
Binary: 01010011 01101110 01100001 01110000
Regroup into 6-bit chunks:
010100 110110 111001 100001 011100 00(pad)
20 54 57 33 28
Base64: U 2 5 h c A (+ padding '=')
Result: U25hcA==
Snap becomes U25hcA==. The trailing = is padding to make the length a multiple of 4. Anyone who sees U25hcA== can reverse it in one step and get Snap back — no key required. That's the entire point and also the entire danger of treating it as a secret. You can encode and decode either direction with a Base64 Encoder.
The critical takeaway: Base64 is NOT encryption. If you Base64-encode a password and store it, you have stored the password in plaintext with a thin costume on. Any attacker decodes it instantly. The string looks scrambled to a human, which is exactly why this mistake is so common and so dangerous. Encoding obscures nothing from anyone who knows it's encoded — and it's always obvious.
Encryption: secrecy that depends on a key
Encryption transforms readable data (plaintext) into unreadable data (ciphertext) using a key, such that only someone with the correct key can reverse it. This is the real tool for confidentiality. The transformation is reversible — that's the whole point, the recipient must be able to read the message — but reversibility is gated behind the key.
Two broad families:
- Symmetric encryption (e.g. AES): the same key encrypts and decrypts. Fast, used for bulk data — encrypting files, disks, database fields, TLS session traffic.
- Asymmetric encryption (e.g. RSA, elliptic-curve): a public key encrypts, a separate private key decrypts. Slower, used for key exchange and digital signatures — the handshake that bootstraps TLS, for instance.
A worked example, conceptually. With AES you take plaintext and a key:
plaintext: "Meet at noon"
key: a 256-bit secret, e.g. 0x8f3a...c91d
(plus a random IV / nonce)
AES-256 → ciphertext: 4b9e7c1a8f... (looks like random bytes)
Hand that ciphertext to anyone without the key and it's noise — that's the security property. Hand it to someone with the key and they run AES in reverse to recover Meet at noon exactly. The security rests entirely on the key staying secret; the AES algorithm itself is public and well-studied. (In practice you also need a unique IV/nonce per message and an authentication tag, e.g. AES-GCM, so an attacker can't tamper with ciphertext undetected — but the core idea is: reversible, key-gated.)
Encryption is the right choice whenever you need to get the original data back later: a message your recipient must read, a file you'll decrypt, a token your server will validate.
Hashing: a one-way fingerprint
Hashing runs data through a one-way function that produces a fixed-size output (a digest), with no way to reverse it back to the input. There is no key. There is no decrypt step. That irreversibility isn't a limitation to work around — it's the entire value.
A cryptographic hash function (SHA-256, for example) has defining properties:
- Deterministic — the same input always yields the same digest.
- Fixed-size output — SHA-256 always produces 256 bits (64 hex characters), whether you hash one byte or a gigabyte.
- One-way (preimage resistance) — given a digest, you can't compute an input that produces it, short of guessing.
- Collision resistant — it's computationally infeasible to find two different inputs with the same digest.
- Avalanche effect — changing one bit of input flips about half the output bits, unpredictably.
Worked example — hello versus Hello under SHA-256:
SHA-256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA-256("Hello") = 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969
One capital letter, and the digests share essentially nothing. That's the avalanche effect. And there is no function that turns 2cf24dba... back into hello — you can only guess inputs and check. You can compute these digests with a Hash Generator.
Hashing is the right tool when you need to verify something without storing it: checking file integrity, deduplicating data, and — most importantly — handling passwords.
Why you hash passwords but encrypt messages
This is where the distinction stops being academic. The rule:
- Hash passwords. Encrypt messages.
A message has to be read again, so it must be reversible — encrypt it. A password should never need to be recovered, only checked, so make it irreversible — hash it.
When a user signs up, you store the hash of their password, never the password. At login, you hash what they typed and compare digests. If they match, the password was correct — and you proved it without ever storing the password itself. If your database leaks, attackers get digests, not passwords. Had you encrypted passwords instead, a single leaked key would expose every one of them. Irreversibility is the feature.
But plain hashing isn't enough for passwords, for two reasons:
-
Identical passwords produce identical hashes. Two users with
password123get the same digest, which is visible in a leak. The fix is a salt — a unique random value stored alongside each user and mixed into the hash. Now identical passwords produce different digests, and precomputed "rainbow tables" of common-password hashes become useless. -
General-purpose hashes are too fast. SHA-256 is built for speed — billions of operations per second on a GPU — which is great for file checksums and terrible for passwords, because it lets attackers guess billions of candidates per second against a stolen hash. Password hashing deliberately uses slow, memory-hard algorithms designed for exactly this job: bcrypt, scrypt, or Argon2. They're intentionally expensive, so each guess costs the attacker real time and memory, throttling offline cracking to a crawl.
So the correct way to store a password is: salt it, then run it through a slow password-hashing function like Argon2 or bcrypt. The right way to handle that password in the first place is to make it strong and random — a Password Generator gives you a value with enough entropy that even a well-resourced offline attack against the hash is hopeless.
The cheat sheet
When you're unsure which word — and which tool — you actually want, ask the reversibility question:
- Need to change format for transport or storage, no secrecy involved? That's encoding (Base64). Reversible by anyone. Never use it to hide anything.
- Need to keep something secret but read it back later? That's encryption (AES, RSA). Reversible only with the key. Protect the key above all else.
- Need to verify something without storing or recovering it? That's hashing (SHA-256 for integrity; bcrypt/scrypt/Argon2 with a salt for passwords). Not reversible, ever — and that's exactly why it's safe.
Three operations, one question. Once you reflexively ask "reversible, and does it need a secret?", you'll never call Base64 "encryption" again.