Hashing vs. encryption vs. encoding: a distinction worth getting right
Three words developers use interchangeably that mean completely different things. Confusing them causes real security bugs — here's the clean mental model.
Few mix-ups in software cause as much quiet damage as conflating hashing, encryption, and encoding. They sound related, they all transform data, and they're used in overlapping contexts — so it's easy to say "we encrypted the passwords" when you meant hashed, or "it's encoded so it's secure" when encoding provides zero security. Each mistake maps to a real vulnerability.
Here's the clean distinction, the one-line test for telling them apart, and where each one actually belongs.
The one-question test
The fastest way to tell these apart is to ask: can you get the original data back, and what do you need to do it?
| Reversible? | Needs a key? | Purpose | |
|---|---|---|---|
| Encoding | Yes | No | Represent data in a different format |
| Encryption | Yes | Yes | Keep data secret from those without the key |
| Hashing | No | No | Produce a fixed fingerprint of data |
Three different answers, three different jobs. Get this table into your head and the rest is detail.
Encoding: format translation, zero secrecy
Encoding transforms data into a different representation so some channel can carry it. Base64 turns binary into text-safe characters; URL encoding escapes characters that would break a URL; ASCII and UTF-8 map characters to bytes.
The defining property: anyone can reverse it, no key required. That's not a weakness of encoding — it's the entire point. Encoding exists to solve compatibility problems ("this channel only accepts text"), never secrecy problems.
The dangerous misconception is treating encoding as protection. A Base64 string
looks scrambled to a human, so people occasionally "hide" an API key or a
password by Base64-encoding it. This protects nothing. cGFzc3dvcmQ= is one
decode away from password. If you find credentials that are "protected" only by
encoding, treat them as plaintext, because that's exactly what they are.
Use encoding when: you need to move binary through a text channel, embed data in a URL, or store bytes in a text field. Never when you need something to stay secret.
Encryption: reversible, but only with the key
Encryption transforms data so that only someone holding the right key can turn it back. Without the key, the ciphertext is (for well-chosen algorithms) computationally useless. This is the tool for confidentiality — keeping data readable to authorized parties and opaque to everyone else.
There are two families:
- Symmetric encryption (e.g. AES) uses the same key to encrypt and decrypt. Fast, ideal for encrypting data at rest — database fields, files, backups.
- Asymmetric encryption (e.g. RSA, elliptic-curve) uses a public key to encrypt and a private key to decrypt. This is what lets two strangers establish a secure channel without pre-sharing a secret; it underpins TLS and the padlock in your browser.
The critical property that separates encryption from hashing: it's designed to be reversed — by whoever holds the key. That's a feature when you need to read the data back (decrypt a stored document) and a liability when you don't (you should never be able to decrypt a stored password).
Use encryption when: you need to store or transmit data that must be recoverable later but kept secret in the meantime — messages, files, sensitive database columns, anything in transit.
Hashing: a one-way fingerprint
Hashing runs data through a function that produces a fixed-size output — the hash, or digest — and it is deliberately impossible to reverse. You cannot get the input back from the output, not even with unlimited compute (for a good hash), because information is genuinely destroyed. A hash of a 2 GB file and a hash of the word "hi" are the same length.
Good cryptographic hashes (SHA-256, SHA-3) have two more essential properties:
- Deterministic: the same input always yields the same hash.
- Avalanche effect: changing a single bit of input scrambles the entire output unpredictably.
- Collision-resistant: it's infeasible to find two inputs with the same hash.
These make hashing perfect for two jobs: verifying integrity (does this file match the hash the publisher posted? if one byte changed, the hash won't match) and storing passwords (store the hash, never the password; on login, hash what the user typed and compare).
The password-hashing subtlety
"Hash your passwords" is right, but which hash matters enormously. General-purpose hashes like SHA-256 are fast — and fast is bad for passwords, because an attacker who steals your database can try billions of guesses per second. Password storage uses deliberately slow algorithms built for the job: bcrypt, scrypt, or Argon2, combined with a salt (a unique random value per password, so identical passwords don't produce identical hashes and precomputed "rainbow tables" are useless). If you ever find passwords stored as plain SHA-256 or, worse, MD5, that's a finding — modern practice is a slow, salted, purpose-built password hash.
Use hashing when: you need to verify that data is unchanged, store passwords, build a checksum, deduplicate by content, or index data by fingerprint.
Putting them together: a login flow
A single real feature uses all three, correctly:
- The user submits a password over an encrypted TLS connection (confidentiality in transit).
- The server hashes it with Argon2 + salt and compares against the stored hash (it never stores or decrypts the actual password).
- On success, the server issues a session token whose payload is encoded in Base64URL (format-safe transport) and signed with a hash-based signature (integrity).
Encryption protects it on the wire, hashing protects it at rest, encoding packages the token. Swap any one for another and you've built a vulnerability: encode the password instead of hashing it and a database leak exposes every credential; hash the data you need to read back and it's gone forever.
Experiment to build intuition
The properties are easier to feel than to read about. Run some text through a Hash Generator and watch the avalanche effect: change one character and the entire digest changes, but the length never does. Then run the same text through a Base64 Encoder and confirm you can decode it straight back — no key, fully reversible. Seeing the one-way irreversibility of a hash next to the trivial reversibility of an encoding makes the distinction stick.
The takeaway
Ask one question: can you get the original back, and what does it take? Encoding is reversible by anyone — it's for compatibility, not secrecy. Encryption is reversible only with a key — it's for keeping data readable to the right people and opaque to everyone else. Hashing is not reversible — it's a fingerprint, for integrity checks and password storage (with a slow, salted algorithm). Three answers, three jobs. Keep them straight and you'll avoid a whole category of security bugs.