Hash and HMAC Generator: MD5, SHA-256, SHA-512 Online

Hash and HMAC Generator: MD5, SHA-256, SHA-512 Online

Compute an MD5 or SHA digest, or sign a message with HMAC, in the browser. Hex, Base64 or Base64URL — text checksums and webhook signatures, 100% local.

21.09.2026
11 min read
Share this article:
Hash
HMAC
SHA-256
Checksum
Security
Tutorial

A digest proves the bytes; HMAC proves who sent them

A hash and an HMAC answer different questions. SHA-256 of a string tells you whether that string still matches a published fingerprint. HMAC-SHA-256 of the same string, plus a shared secret, tells you whether someone who knows the secret produced it. Neither one is encryption, and neither one is a password store. FastMinify splits the jobs: the online hash generator computes MD5, SHA-1, SHA-256, SHA-384 and SHA-512 from UTF-8 text, and the HMAC generator signs a message with HMAC-SHA-256, SHA-384 or SHA-512. Both run in the tab via Web Crypto (MD5 is a local implementation, because Web Crypto does not offer it). Nothing is uploaded. Both live on the encoding tools hub, next to Base64 and JWT helpers — encoding is how you spell bytes, hashing is how you fingerprint them.

Five digests at once on the hash page: SHA-256, SHA-384, SHA-512, SHA-1, MD5
HMAC limited to SHA-256, SHA-384 and SHA-512 — no MD5 or SHA-1 keyed mode
Output: lowercase or uppercase hex, padded Base64, or unpadded Base64URL
Paste an expected digest: matching algorithms are highlighted; hex case, spaces and Base64URL padding are ignored
HMAC key encoding: UTF-8 text (default), hex bytes, or Base64 / Base64URL bytes
Hash page accepts a text file (txt, md, json, csv, html, xml, yml, yaml) up to 32 MiB, read as UTF-8 — not a binary sha256sum

When the browser is the right place to hash

Good fits

A string you can paste, a secret you are willing to type into your own browser, a digest you already hold.

Checking SHA-256 of a short fixture against a unit test or a doc example (abc, empty-string digests in a REPL — the page itself clears the result when the box is empty or whitespace)
Comparing a JSON or YAML body you just edited with the digest your colleague sent, after you agree on LF vs CRLF
Reproducing a GitHub-style HMAC of the raw body, then comparing the hex without the sha256= prefix
Seeing which algorithm a mystery hex belongs to: paste it in Expected digest and let the five cards light up
Teaching the gap between Base64, a hash, and HMAC without installing Node
Leave it to the machine that holds the file or the key

If the bytes are a binary artifact, or the secret must not appear in a browser on a shared machine, stay in the shell or in CI.

Release tarballs, containers, images, PDFs — sha256sum or openssl dgst on the file, not this page
Files over 32 MiB, or extensions outside the text allowlist — the picker refuses them
Password databases — <a href="/en/bcrypt-hash" class="text-primary hover:underline">bcrypt</a>, not SHA
A JWT you need to accept or reject — <a href="/en/jwt-verify" class="text-primary hover:underline">jwt-verify</a>, not a hand-rolled HMAC of the payload JSON
A repo that might already contain a leaked signing secret — <a href="/en/scan-secrets" class="text-primary hover:underline">scan secrets</a> before you rotate the key you just pasted

Hash mistakes that look like a match and are not

Using SHA or MD5 as a password hash

A plain digest is fast, unsalted, and identical for the same input. That is what you want for a checksum. It is what you do not want for a password: an attacker precomputes the digest, and two users with the same password share a row. FastMinify's hash and HMAC pages say so in the docs. Password storage belongs on bcrypt-hash (or Argon2 on your server). HMAC is also the wrong tool: it authenticates a message with a secret you must keep, it does not stretch a password.

Storing SHA-256(password) and calling the column hashed
Using HMAC(password, pepper) as a substitute for bcrypt because it feels keyed
Comparing MD5 of a passphrase to decide a login
Assuming a longer digest (SHA-512) fixes the missing salt and the missing work factor
Treating a hash as a signature, or Base64 as a hash

Anyone can recompute SHA-256 of a public body. The digest proves the body did not change; it does not prove who produced it. If a webhook, a release note, or an API call must be authentic, you need a secret: HMAC, or a JWT signature checked with jwt-verify. The reverse confusion is just as common after the Base64 encode and decode guide: Base64 is reversible wrapping. SHA-256 of abc is ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad. You cannot turn that hex back into abc.

Publishing a SHA-256 next to a JSON body and calling the body signed
Decoding a digest with the Base64 tool and expecting the original text
Pasting a JWT into the hash generator to see if it is valid
Hiding an API key by hashing it, then being unable to recover the key the server still needs
Checksum of a file that is not the bytes on disk

The hash generator hashes UTF-8 text, not a raw file. Upload accepts text extensions only — txt, md, json, csv, html, xml, yml, yaml — up to the 32 MiB client cap, and the file is decoded as text before hashing. A vendor SHA-256 of a .tar.gz, an image, or a PDF will not match, and those types are not in the picker. Even a text file can disagree with sha256sum when the newline convention changes. SHA-256 of abc is the vector above. SHA-256 of abc plus a single LF is edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb. Same letters, different bytes.

Dropping a release tarball and expecting the vendor checksum
Comparing a Windows CRLF file with a Linux LF digest
Using <code>echo abc | sha256sum</code> (echo adds a newline) and blaming the browser
Renaming a binary to .txt so the picker accepts it — the bytes are no longer the file
Signing a different string than the webhook

GitHub's X-Hub-Signature-256 is sha256= plus HMAC-SHA-256 of the raw body, secret as UTF-8. Stripe signs timestamp.payload, not the JSON alone. The HMAC page does not build those strings and does not strip a sha256= prefix. Paste the exact message, the exact key bytes, and only the digest. Expected-digest comparison ignores hex case and spaces, and trailing = on Base64URL. It does not ignore a prefix.

Pasting the whole header <code>sha256=f7bc…</code> into Expected digest
Pretty-printing the JSON before signing — spaces change the HMAC
Leaving Key encoding on UTF-8 when the secret is a hex or Base64 key
Asking HMAC for MD5 or SHA-1 — those algorithms are hash-only on this site

Which algorithm, which spelling, which tool

Hash, HMAC, bcrypt, JWT — four different locks

They all emit opaque strings. They do not substitute for each other.

Hash generator: no secret. MD5, SHA-1, SHA-256, SHA-384, SHA-512 of UTF-8 text. All five update together; a pasted expected digest highlights the algorithms that match.
HMAC generator: shared secret required. HMAC-SHA-256 (default), SHA-384, or SHA-512. Empty message or empty secret is an error. No file upload.
bcrypt-hash: password storage. Slow on purpose. Do not send a bcrypt string to the hash page and expect a match.
jwt-verify: checks a compact JWT (header.payload.signature) against a key or JWKS. HMAC-SHA-256 is the primitive behind HS256, but the signed input is base64url(header).base64url(payload), not the JSON claims. Use jwt-verify for tokens; use HMAC for a raw message.
Hex, Base64, Base64URL

The digest bytes do not change. The spelling does. Hex is what sha256sum and most webhook docs print. Padded Base64 is what some APIs return. Unpadded Base64URL is the compact form (no +, /, or trailing =). Uppercase applies only to hex.

NIST vector, input abc, SHA-256 hex: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad — 64 hex characters, 32 bytes
Same input, MD5 hex: 900150983cd24fb0d6963f7d28e17f72 — 32 hex characters. Legacy checksums only; do not start a new protocol on MD5 or SHA-1
HMAC-SHA-256, key the four characters key, message The quick brown fox jumps over the lazy dog, hex: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
Same HMAC in padded Base64: 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg= — Base64URL drops the padding and swaps + and /: 97yD9DBThCSxMpjmqm-xQ-9NWaFJRhdZl0edvC0aPNg
Lengths you can check before you trust a paste

A truncated digest is a failed copy, not a different algorithm. Count characters after you strip spaces.

MD5: 16 bytes → 32 hex, or 24 Base64 characters with padding
SHA-1: 20 bytes → 40 hex. Collision attacks exist; keep it for legacy manifests only
SHA-256: 32 bytes → 64 hex, 44 Base64 with one =, 43 Base64URL without padding
SHA-384: 48 bytes → 96 hex. SHA-512: 64 bytes → 128 hex. HMAC output length follows the hash you picked

Compute a digest, then sign a message

Hash a string or a text file

Open the hash generator. Paste the text or upload a text file. Choose hex, Base64, or Base64URL. Turn on uppercase only if the reference digest is printed in capitals — it does nothing for Base64. All five algorithms refresh together. Paste the expected digest to highlight matches. Load sample if you only want to see the pipeline. The box must contain non-whitespace text; an empty field clears the cards instead of showing the well-known empty-string SHA-256.

1

Step 1 — Paste the exact bytes as text

Agree on newlines. A trailing LF is part of the input. Do not pretty-print JSON if the other side hashed the compact form.

2

Step 2 — Match the output spelling

Hex for checksums and CLI tools. Padded Base64 when the API shows + / and =. Unpadded Base64URL when the digest sits in a token or a URL.

3

Step 3 — Paste the expected digest

Comparison ignores hex case and spaces, and Base64URL padding. A match highlights the algorithm. No highlight means different bytes, a different spelling, or a prefix you still need to strip.

Sign with HMAC

Open the HMAC generator. There is no file upload: paste the message and the secret. Pick SHA-256 unless the vendor says SHA-384 or SHA-512. Set Key encoding to UTF-8 for a passphrase-style secret, hex for a hex key (optional 0x prefix, even length), or Base64 when the key was stored that way. UTF-8 on a hex secret signs the characters 0-9a-f, not the key bytes — the digest will not match and the error is not obvious. Expected digest uses the same comparison rules as the hash page.

Algorithms: HMAC-SHA-256 (default), SHA-384, SHA-512 — Web Crypto only
Message and secret are required; whitespace-only values are rejected
Output: hex, padded Base64, unpadded Base64URL; uppercase is hex-only
The secret stays in the tab. Close it when you are done; the page is not a vault
HS256 JWT signing input is not the claims object — use jwt-encode / jwt-verify for tokens

The same bytes in Node and openssl

Node crypto — UTF-8, no extra newline

createHash and createHmac hash the string you pass. They do not add a newline. That matches the browser tools.

Basic example

const crypto = require('node:crypto') const sha256 = crypto.createHash('sha256').update('abc').digest('hex') // ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad const hmac = crypto.createHmac('sha256', 'key') .update('The quick brown fox jumps over the lazy dog') .digest('hex') // f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
openssl — printf, not echo

echo appends a newline, so the digest is of different bytes. printf does not. For a file on disk, pass -binary only when you want raw digest bytes; hex is the default text form.

Basic example

printf 'abc' | openssl dgst -sha256 # ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad printf 'The quick brown fox jumps over the lazy dog' | openssl dgst -sha256 -hmac key # f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 # binary artifact — not the browser tool openssl dgst -sha256 release.tar.gz
FastMinify hash-generator / hmac-generator

No install, no upload, five hash algorithms or three HMAC algorithms, hex / Base64 / Base64URL, and an expected-digest highlight. Trade-off: text and UTF-8 only, 32 MiB text-file cap on the hash page, no binary checksum, no MD5-HMAC, no password stretching, no JWT assembly. Use the pages to inspect a snippet or reproduce a webhook digest. Keep openssl on the release artifact and bcrypt on the password.

Conclusion

Hash the text when you need to know it did not change. HMAC it when a shared secret must prove who produced it. FastMinify does both in the browser: MD5 through SHA-512 for UTF-8 text (and text files up to 32 MiB), HMAC-SHA-256/384/512 with a UTF-8, hex, or Base64 key, spelled as hex, Base64, or unpadded Base64URL. It will not checksum a tarball, store a password, or verify a JWT. Those jobs stay on openssl, bcrypt, and jwt-verify. Start from the encoding tools hub when the string is still just text.

SHA-256 for new checksums; MD5 and SHA-1 only when a legacy manifest demands them
HMAC when there is a shared secret; a bare hash does not authenticate the sender
Match newlines and spelling (hex vs Base64 vs Base64URL) before you call a digest wrong
Text files only in the browser — binary artifacts stay on openssl or sha256sum
Passwords go to bcrypt; tokens go to jwt-verify
Share this article
Share this article: