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:
HashHMACSHA-256ChecksumSecurityTutorial

A digest proves the bytes; HMAC proves who sent them

A hash and an HMAC answer different questions. The SHA-256 of a string tells you whether that string still matches a published fingerprint. The HMAC-SHA-256 of the same string, computed with 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 browser tab through Web Crypto (MD5 is a local implementation, because Web Crypto does not offer it), and nothing is uploaded. Both are listed on the encoding tools hub, next to the Base64 and JWT tools. Encoding is how you spell bytes, and 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, with no keyed MD5 or SHA-1 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
The hash page accepts a text file (txt, md, json, csv, html, xml, yml, yaml) up to 32 MiB, read as UTF-8, so it cannot replace sha256sum for binary files

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 the SHA-256 of a short fixture against a unit test or a documentation example such as abc. An empty field clears the result, so read the empty-string digest in a REPL, not in the tool
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 and PDFs: use sha256sum or openssl dgst on the file, not this page
Files over 32 MiB or with an extension outside the text allowlist, which the picker refuses
Password databases: use bcrypt, not SHA
A JWT you need to accept or reject: use jwt-verify, not a hand-rolled HMAC of the payload JSON
A repository that might already contain a leaked signing secret: scan secrets 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 suits a checksum and does not suit a password: an attacker can precompute the digest, and two users with the same password share the same value. The hash and HMAC pages say so in their documentation. Password storage belongs with bcrypt-hash (or Argon2 on your server). HMAC is also the wrong tool, because it authenticates a message with a secret you must keep and 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
Approving a login by comparing the MD5 of a passphrase
Assuming a longer digest (SHA-512) fixes the missing salt and the missing work factor
Checksums and webhook signatures here. Password storage on bcrypt, with a cost factor your server can afford.
Treating a hash as a signature, or Base64 as a hash

Anyone can recompute the SHA-256 of a public body. The digest proves the body did not change, but 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, because Base64 is reversible wrapping. The SHA-256 of abc is ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad. You cannot turn that hex back into abc.

Publishing the 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
Integrity without a secret → hash. Integrity with a shared secret → HMAC. Confidentiality → encryption, which these pages do not do. Reversible spelling → Base64.
Checksum of a file that is not the bytes on disk

The hash generator hashes UTF-8 text, not a raw file. The file picker accepts text extensions only (txt, md, json, csv, html, xml, yml, yaml), up to the 32 MiB browser limit, 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. The SHA-256 of abc is the vector above. The 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 echo abc | sha256sum (echo adds a newline) and blaming the browser
Renaming a binary to .txt to get past the picker, even though decoding it as text changes its bytes
The page is the right hammer for a snippet, a JSON body, or a text fixture. Binary artifacts stay on sha256sum or openssl dgst.
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 sha256=f7bc… 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 for an HMAC with MD5 or SHA-1, which are available only on the hash page
Reproduce the vendor's exact input. If the signature still misses, the bug is in the bytes you fed, not in a second algorithm.

Which algorithm, which spelling, which tool

Hash, HMAC, bcrypt and JWT are 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, written header.payload.signature, against a key or JWKS. HMAC-SHA-256 is the primitive behind HS256, but the signed input is the two Base64URL parts joined by a dot, not the JSON claims. Use jwt-verify for tokens and 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 in hex: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad (64 hex characters, 32 bytes)
Same input, MD5 in hex: 900150983cd24fb0d6963f7d28e17f72 (32 hex characters). Legacy checksums only; do not start a new protocol on MD5 or SHA-1
HMAC-SHA-256 with the four characters key as the secret and the message The quick brown fox jumps over the lazy dog, in hex: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
The same HMAC in padded Base64 reads 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=. Base64URL drops the padding and replaces the plus sign and the slash with a hyphen and an underscore, giving 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 and SHA-512 give 48 and 64 bytes, that is 96 and 128 hex characters. 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 select a text file. Choose hex, Base64 or Base64URL. Turn on Uppercase hex 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, or load the sample if you only want to see how it works. The box must contain at least one character that is not whitespace: an empty field clears the cards instead of showing the well-known SHA-256 of the empty string.

1

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

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

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 selection, so 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, to hex for a hex key (optional 0x prefix, even length), or to Base64 or Base64URL when the key was stored that way. With UTF-8 on a hex secret, the page signs the characters 0-9a-f, not the key bytes, so the digest does not match, and the cause is hard to spot. Expected digest follows the same comparison rules as the hash page.

Algorithms: HMAC-SHA-256 (default), SHA-384, SHA-512, all through Web Crypto
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
The signing input of an HS256 JWT is not the claims object: use jwt-encode / jwt-verify for tokens

The same bytes in Node and openssl

Node crypto with UTF-8 and 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 with 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, nothing sent to a server, five hash algorithms or three HMAC algorithms, hex / Base64 / Base64URL, and an expected-digest highlight. The limits: text and UTF-8 only, a 32 MiB cap for text files on the hash page, no binary checksum, no HMAC with MD5, no password stretching, no JWT assembly. Use the pages to inspect a snippet or reproduce a webhook digest. Keep openssl for the release artifact and bcrypt for the password.

Conclusion

Hash the text when you need to know it did not change. Use HMAC when a shared secret must prove who produced it. FastMinify does both in the browser. It handles MD5 through SHA-512 for UTF-8 text (and text files up to 32 MiB), and HMAC-SHA-256, SHA-384 or SHA-512 with a UTF-8, hex or Base64 key, written as hex, Base64 or unpadded Base64URL. It will not checksum a tarball, store a password or verify a JWT. Those jobs stay with 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 with openssl or sha256sum
Passwords go to bcrypt; tokens go to jwt-verify
Share this article
Share this article: