Hash Generator
SHA-1, SHA-256, SHA-384 and SHA-512 over text or a file — and the reason your hash does not match theirs.
the digests appear here as you type
compare against a published value — it names the algorithm and points at the first mismatch
A hash is over bytes, never over text
Choose any of SHA-1, SHA-256, SHA-384 or SHA-512 and MD5 (when you switch it on) — the
page computes every selected algorithm at once, one row each, because at
browser-digest speed the difference between computing one and computing all four is
nothing. The input pane accepts text or a file: a dropped file is hashed as its raw
bytes, and text goes through the encoding you name rather than one the page guesses.
UTF-8, UTF-16LE, hex and base64 are all on the control, because a hash never sees the
string you pasted — it sees whatever bytes the encoding produced. Type
café and you are hashing five bytes; switch to UTF-16LE and the
same text is eight, and the digest is different. Neither is wrong; they answer
different questions, and the page tells you which one it just answered.
That is the page’s actual job, though, and it is not the digest. It is the four answers to the question everyone brings here — why does my hash not match theirs? A trailing newline (the control under the input picks either reading and shows both digests side by side), an encoding nobody stated (the notes strip names the one in use and flags a BOM, which is invisible on screen), a message that was normalised differently than the recipient’s copy, and an algorithm nobody named (the expected-value box reads a pasted checksum, any case, with or without a prefix or a trailing filename, and tells you whether it matches — and which algorithm it is). The only non-browser algorithm is MD5, which Web Crypto deliberately does not carry; it loads a small implementation when you turn it on, with the honest caveat that MD5 is broken for anything security-bearing.
Generate the same hash without this page
The digests that follow are the ones this page produces for the same input, so whatever you compare against can be checked against the rows above without leaving. The first snippet carries the pitfall that costs people a whole afternoon.
printf 'hello' | shasum -a 256 # 2cf24dba5fb0a30e26e83b2ac5b9e29e1… (macOS) echo 'hello' | shasum -a 256 # 5891b5b522d5df086d0ff0b110fbd9d2… ← echo adds a newline printf 'hello' | sha256sum # 2cf24dba5fb0a30e26e83b2ac5b9e29e1… (GNU coreutils) printf 'hello' | sha384sum printf 'hello' | sha512sum # shasum -a 384 and shasum -a 512 do the other two; every value above # matches the row on this page for the same input.
printf 'hello' | openssl dgst -sha256 # 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 openssl dgst -sha256 file.bin # a whole file, raw bytes openssl dgst -sha512 file.bin
$bytes = [Text.Encoding]::UTF8.GetBytes('hello')
$hash = Get-FileHash -Algorithm SHA256 -InputStream ([IO.MemoryStream]::new($bytes))
$hash.Hash.ToLower() # 2cf24dba5fb0a30e26e83b2ac5b9e29e1… — matches the row above
# Get-FileHash defaults to SHA256 and prints the digest in upper case;
# .ToLower() exists only to line it up with every other tool.
certutil -hashfile file.bin SHA256 # A file whose content is exactly "hello" (no trailing newline) prints: # SHA256 hash of file.bin: # 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 # certutil hashes files, not strings; drop the same file here for the # same value — raw bytes in, raw bytes out.
The specs this page implements
FIPS 180-4 defines the four SHA-2 algorithms whose abc vectors are
pinned in this page’s tests. RFC 2104 defines HMAC, the construct the
toggle computes — HMAC-SHA-256 over the same bytes with the key you type, the
exact machinery behind an HS256 JWT signature, which is why the
jwt-debugger page links here. RFC 6234 covers the whole SHA family in one
document for the reference-implementation crowd. And the W3C Subresource Integrity
specification is where the sha384-+base64 form comes from: a digest of
the served resource, in the alphabet a URL survives in, so the browser can refuse to
run bytes that do not match what the page author certified.
FAQ
Why does `echo hello | sha256sum` give a different hash than this page?
echo appends a newline and printf does not, so the value
from a terminal is usually the hash of your string plus one byte.
Measured here: sha256sum of "hello" is
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824, and of
"hello\n" it is
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03. This is
the everyday hash mismatch, so the answer here is a control rather than a paragraph
nobody reads. Under the input, hashed text ends with offers
no newline (printf) and \n (echo), and both
digests stay on screen so you can see which one you are being compared against
without touching it. It works in both directions deliberately: if what you pasted
has no trailing newline but the checksum you were given came out of
echo, the control you need is the one that adds the byte, and a
toggle that could only strip a newline it found would never have appeared for you.
Is SHA-1 safe to use?
Not as a security primitive: the SHAttered team published two different PDFs with
the same SHA-1 in 2017, and attacks have only gotten cheaper since. But SHA-1 is
still honest for a non-adversarial integrity check — confirming a download was
not truncated, not that it was not tampered with. This page keeps it listed with the
other three because the sha1sum question is real, and refusing to
answer it would make the page less useful without making anyone safer.
Why is MD5 not available in the browser, and why do you include it anyway?
MD5 is deliberately absent from Web Crypto — a working-group decision, not an
omission. But md5sum output is still what a decade of download pages
publish, so the MD5 row here works by loading a small JavaScript implementation
(js-md5, ~3.4 kB gzipped) on first use, on a page that otherwise ships none. It
is fine for checking a download was not truncated and useless for anything an
attacker might also compute, and the copy beside the toggle says exactly that rather
than pretending otherwise.
What does the `sha384-` prefix in an SRI attribute mean?
An integrity attribute is the SHA-384 digest of the resource in base64, not
hex, so switch this page’s output control to base64 and a value
pasted from a <script> tag lands in plain view. Measured this
session for hello:
sha384-WeF0h3dEjGnea4ANejO7+5/xtGPkQ1TDVTvNucZm+pASWjx5+QOXvfX2oT3oKGhP
— a 48-byte digest encodes evenly, so it carries no padding. It is the same
digest this page computes, in a different alphabet.
Why does `git hash-object` not match `sha1sum` of the same file?
git does not hash the file; it prefixes the content with blob
<byte-length>\0 and hashes that. Measured:
printf "hello" | git hash-object --stdin is
b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0, byte-for-byte the same as
printf "blob 5\0hello" | shasum -a 1. Paste it as hex on this page and
the SHA-1 row reproduces exactly what git sees, because git’s input is bytes,
not text.
Can a hash be reversed? Can you "decrypt" my md5?
No, and the pages that offer to “decrypt md5” are not decrypting anything. Hashing is one-way: 64 hex characters cannot be turned back into bytes. What those pages run is a lookup against a rainbow table — a precomputed dictionary of hashes of known inputs. If your input is in the dictionary they hand you the match; if it is not, you get nothing. That is also why hashing a password with SHA-256 here would be teaching the wrong thing: password hashing is a key-derivation job (PBKDF2, scrypt, argon2), not a digest over raw bytes, and this page stays honest about not being one.