Notes
Hashing, HMAC, and encryption answer three different questions
All three get called "encrypt it". Whether you can recover the input, whether a key is involved, and what that key proves are different. This note puts the three paths side by side and maps them to browser APIs.
By Brook/Updated 2026-10-09/11 min read
Start from the question you need answered
A hash asks whether this content is the same as a previous copy. An HMAC asks whether someone holding a key accepted this content. Encryption asks whether someone without the key can read the original. A system can need all three. It cannot use one operation as a stand-in for the other two.
Mixed names produce mixed designs. "Encrypting" passwords into a database, if the operation is reversible, means a leaked key restores every password. A fast hash with no salt fails open against a precomputed table. Name the question, then pick the algorithm.
Three paths, side by side
Hash
No key. The same input always yields the same digest.
- Fixed length
- No path back to the input
- One flipped bit changes the digest
- SHA-256 fits integrity checks
HMAC
A hash plus a key. Without the key you cannot produce a digest that verifies.
- Proves possession of the key
- Still not reversible
- Key and message go in together
- HS256 on a JWT is this
Encryption
The key is what restores the plaintext.
- AES-GCM also covers integrity
- Needs an IV or nonce
- Do not store the key with the ciphertext
- Plaintext can be recovered
A hash has no key, so it cannot prove identity. Anyone can compute SHA-256 over public content. It is the right tool for "did this file change": store the digest, recompute later, compare. It is the wrong tool for "did a particular person agree", because anyone can compute that digest.
HMAC is a digest that includes a key
HMAC mixes the key into the hash input: two padded blocks derived from the key, then two rounds of hashing with the message. You should not assemble that by hand. Crypto libraries and Web Crypto already expose HMAC. What you do need to remember: verify with the same key and the same hash, and compare digests in constant time rather than with a string compare that returns early.
A short or guessable key makes HMAC weak. A username, or the literal "secret", is close to having no key. The key should be long random bytes, not a passphrase. A passphrase has to go through a dedicated stretching function before it becomes key material. That is a separate path.
Encryption is reversible, so it needs an IV
A block cipher such as AES needs an IV or a nonce so the same key and the same plaintext do not always produce the same ciphertext. The IV is not secret, but it must not be reused under the same key, especially for CTR and GCM. GCM also returns an authentication tag. If the tag does not match, fail the decrypt. Do not hand a partial plaintext to the application.
Ciphertext, IV, and tag have to be stored together. Drop any one of them and you cannot decrypt. Wrapping them in a text encoding, often Base64, is a storage format. It is not part of the cipher. Decoding Base64 only returns bytes. You still have to decrypt.
Things that look like encryption and are not
- Base64 is not encryption. Anyone can reverse it. There is no key.
- MD5 is no longer a safe digest. Practical collisions exist. Use SHA-256 or stronger for integrity.
- A hash with no salt is a poor password store. Identical passwords share a digest, so a table can be built ahead of time.
- XOR with a fixed constant is not a scheme. Once that constant ships in frontend code, it is public.
Password storage wants a slow hash and a unique salt: Argon2, bcrypt, or scrypt. SHA-256 is fast, which is why it does not replace those. The hash tool on this site checks digests and compares files. It does not produce a password hash you should insert into a user table.
In the browser, all three go through Web Crypto
- 01PageThe text or file you pastedTurn it into bytes first. Text uses UTF-8. Files use raw bytes. Do not Base64 them before the operation.
- 02Web Cryptodigest, sign, or encryptSHA-256 uses digest, HMAC uses sign, AES-GCM uses encrypt. The algorithm name is part of the call.
- 03ResultDigest or ciphertext stays on the pageEncode to hex or Base64 only when you need to copy it. Encoding happens after the operation.
Web Crypto is asynchronous and takes an ArrayBuffer. Text has to go through TextEncoder as UTF-8, or a digest of non-ASCII text will disagree with an implementation that hashed UTF-16 by mistake. The calls run locally. The hash and AES tools on this site follow that path. The input is not sent as a request body.
Tools mentioned here
Keep reading
- How JSON parsing works, from characters to a valueFormat, minify, and tree view look like three buttons. Underneath they share one pipeline: split the text into tokens, then fold those tokens into a value. This note walks that path and shows where line numbers come from.
- What UTF-8 actually encodesCharacter counts, code points, and bytes are three different rulers. This note walks one code point through UTF-8 and explains why URL encoding and JSON escapes look nothing like each other.
- The three parts of a JWT, and what verification checksDecoding the header and payload does not mean the token can be trusted. This note separates Base64URL, the signature, and claim checks, and explains why the algorithm and the key have to be chosen together.