Hashing, encryption and encoding are three different things
They get used interchangeably in conversation and they are not remotely interchangeable in practice. Confusing two of them is behind a large share of real security failures.
Three words that get swapped freely in conversation and mean completely different things. The confusion is not academic: "we encrypted the passwords" and "we hashed the passwords" describe different systems with different consequences when one is breached, and "we encoded it" describes no security at all.
Encoding: changing the format
Encoding converts data from one representation to another so that some system can carry it. Base64 turns arbitrary bytes into 64 safe characters so binary can travel through channels that only accept text. URL encoding turns a space into %20 so a URL stays parseable. UTF-8 turns characters into bytes.
There is no key and no secret. The scheme is public and the whole point is that anyone can reverse it — that is what makes it useful. Encoding is about compatibility, not confidentiality.
Which is why "the password is Base64 encoded" is not a security measure but a description of the file format. Anyone can paste it into a Base64 decoder and read it, and that is not a flaw in Base64. It is what Base64 is for.
The mistake shows up regularly in real systems: HTTP Basic authentication sends credentials Base64-encoded, and people see the gibberish and assume it is protected. It is not. Over plain HTTP those credentials are readable by anyone on the path. TLS is what protects them; the Base64 is packaging.
Encryption: reversible, with a key
Encryption transforms data so it cannot be read without a key, and can be perfectly recovered with one. Two-way, by design.
Two families. Symmetric encryption — AES being the one you will meet — uses the same key to encrypt and decrypt. It is fast and it is what protects data at rest: disk encryption, database fields, encrypted backups. The hard part is not the algorithm, it is getting the key to the other party without it being intercepted.
Asymmetric encryption — RSA, and increasingly elliptic-curve schemes — uses a key pair. Anything encrypted with the public key can only be decrypted with the private one. That solves key distribution, since the public key can be published, and it is what underlies TLS certificates and signed messages. It is also much slower, which is why TLS uses asymmetric cryptography only to agree a symmetric key, then switches.
Use encryption when you need the original back: card details you must charge later, messages the recipient must read, files that have to be restored.
Hashing: one-way, on purpose
A hash function takes input of any size and produces a fixed-size output. SHA-256 always produces 256 bits, whether the input is one character or a gigabyte.
The defining property is that it is not reversible. Not "hard to reverse" — there is no inverse function, because information has been destroyed. Infinitely many inputs map to any given 256-bit output; the hash cannot tell you which one you started with.
Good hash functions also guarantee:
- Determinism. The same input always gives the same output.
- Avalanche. Change one bit of input and roughly half the output bits change. Similar inputs do not produce similar hashes, so you can learn nothing about the input by comparing hashes.
- Collision resistance. Finding two inputs with the same hash should be computationally infeasible. MD5 and SHA-1 have both failed this test and are broken for any security purpose because of it.
Use hashing when you never need the original: verifying a password without storing it, checking a downloaded file is intact, detecting whether a document changed.
The distinction that matters most
Passwords must be hashed, never encrypted.
Encryption implies a key, the key must live somewhere your application can reach, and anyone who breaches the application usually reaches the key too. A breach then yields every password in plaintext.
Hashed passwords have no key to steal. Verification works by hashing what the user typed and comparing — the system never needs to know the original, and neither does an attacker who takes the database.
And a further point people miss: a general-purpose hash is not enough either. SHA-256 is designed to be fast, which is exactly wrong for passwords, because fast means an attacker can try billions of guesses per second. Password hashing needs a deliberately slow function — bcrypt, Argon2, scrypt — with a per-user salt. That is a large enough topic to have its own guide.
HMAC: the one that combines two of them
An HMAC is a hash computed with a secret key mixed in. It answers a question a plain hash cannot: did this come from someone who knows the secret, and has it been altered?
A plain hash proves integrity only if the hash itself arrived through a trusted channel — otherwise an attacker who changes the message simply recomputes the hash. An HMAC cannot be recomputed without the key, so it proves integrity and authenticity together.
This is what signs webhooks, API requests and JWTs. When Stripe or GitHub sends your server an event, the signature header is an HMAC — you recompute it with your shared secret and compare. If it matches, the payload is genuine and unmodified.
One detail with real consequences: compare HMACs in constant time. A normal string comparison returns as soon as it finds a difference, and the timing of that return leaks how many leading bytes were correct. Repeated enough, that recovers the signature. Every language has a constant-time comparison function for exactly this; use it.
Our HMAC generator computes them with the common algorithms if you need to verify a webhook signature by hand while debugging.
Choosing, in one line each
- Need the data back, need it secret → encryption
- Never need the data back, only need to check a match → hashing
- Need to check a match on a password specifically → slow password hashing, not SHA-256
- Need to prove a message is genuine and unmodified → HMAC or a digital signature
- Need to move data through a system that mangles it → encoding, and understand it protects nothing
The tell-tale mistakes
"We encrypt passwords." Either a wording slip or a real architectural problem. Worth asking which.
"It's encoded so it's safe." It is not. Encoding is reversible by anyone by definition.
MD5 or SHA-1 for anything security-related. Both have practical collision attacks. MD5 remains fine as a non-security checksum for accidental corruption — our MD5 generator exists for exactly that, verifying a file matches a published checksum — and it must not be used where an adversary is involved.
Writing your own crypto. The algorithms are public and the implementations are the hard part: timing, padding, key handling, randomness. Every widely used language has a vetted library. Use it.
Tools mentioned in this guide
SHA256 Generator
Generate a SHA-256 hash of text or a file in your browser — the current standard for checksums, signatures and integrity checks.
MD5 Generator
Generate an MD5 hash of text or a file in your browser, with the digest updating as you type and nothing uploaded.
Base64 Encoder
Encode text or a file to Base64 in your browser, with URL-safe output, MIME line wrapping and ready-to-paste data URIs.
Base64 Decoder
Decode Base64 back to text or a file in your browser — accepts URL-safe input, missing padding and data URI prefixes.
HMAC Generator
Generate an HMAC signature with MD5, SHA-1, SHA-256, SHA-384 or SHA-512 and a secret key — the way webhook signatures are verified.
More guides
- Why your link looks wrong when you share it Without Open Graph tags, every platform guesses what your page is about — and they guess badly, cache the guess, and give you no obvious way to correct it.
- Base64: what it is for, and when it quietly costs you It exists to move binary data through channels that only accept text. It is not compression, it is not security, and it makes everything about a third bigger.
- How to shrink a video enough to actually send it Every service has a different ceiling — 25 MB, 16 MB, 100 MB — and hitting it is not guesswork. Work backwards from the limit and the settings choose themselves.