MD5, SHA-1 and SHA-256 checksums: why yours does not match

Updated 5 min read

You hash a string in the browser, a colleague hashes the same string in a terminal, and the digests differ. Nothing is wrong with either hash function. The two inputs were different byte sequences, and a hash only ever sees bytes.

Same text, different bytes

A hash function takes bytes, so every step that turns text into bytes is part of the input. These are the usual causes of a mismatch, roughly in order of how often they bite:

  • A trailing newline. echo abc | sha256sum hashes abc plus a newline, four bytes instead of three. Use printf abc | sha256sum or echo -n abc to hash exactly what you typed.
  • Line endings. A file checked out with CRLF line endings on Windows and the same file with LF on Linux are different files to a hash. One flipped byte per line changes the whole digest.
  • A byte-order mark. Some editors and PowerShell redirections write EF BB BF at the start of a UTF-8 file. It is invisible in the editor and part of the input to the hash.
  • The encoding. é is C3 A9 in UTF-8 and E9 in Latin-1; Chinese characters take three bytes in UTF-8 and two in GBK. A tool that hashes UTF-16, which is what some Windows APIs default to, produces a third answer. The hash generator below always encodes text as UTF-8.
  • Hidden whitespace. A trailing space copied from a web page or terminal is enough.

When a checksum does not match, compare lengths before anything else. The status line of the tool reports how many bytes the digests were computed over; if you expected 3 and it says 4, you have found the newline.

Digest sizes and values you can check

Run these against any implementation as a smoke test:

AlgorithmDigest sizeHex lengthDigest of the empty string
MD5128 bits32d41d8cd98f00b204e9800998ecf8427e
SHA-1160 bits40da39a3ee5e6b4b0d3255bfef95601890afd80709
SHA-256256 bits64e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

For the three bytes abc, MD5 is 900150983cd24fb0d6963f7d28e17f72, SHA-1 is a9993e364706816aba3e25717850c26c9cd0d89d and SHA-256 is ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad. SHA-384 and SHA-512 have 96 and 128 hex digits. Changing a single input bit changes about half the output bits, so a digest that looks nearly right is just as wrong as one that looks entirely different.

What is actually broken

“MD5 is broken” has a narrow meaning: it is possible to construct two different inputs with the same MD5. That was first shown in 2004, and chosen-prefix collisions have since been used to forge a certificate and in real malware. SHA-1 fell to a published collision in 2017. Both still detect random corruption perfectly well, which is why you see them next to old downloads.

What they no longer do is stop an attacker. If someone can craft a file, a matching MD5 or SHA-1 proves nothing. Where an attacker is in the picture, use SHA-256 or stronger, and remember the second weakness: a checksum published on the same page as the download is only as trustworthy as the page. An attacker who can replace the file can replace the checksum. A signature, or a checksum fetched over a separate trusted channel, is what adds trust. The tool prints a note beside the table that MD5 is a legacy checksum for this reason.

Which to pick

PurposeSuggestion
Detecting transfer corruption, no attackerany of them; SHA-256 is the default that ends the discussion
Integrity against deliberate tamperingSHA-256 or stronger, plus a signature or a separate channel
Cache keys and de-duplicationSHA-256; MD5 only if nobody can craft colliding inputs
Storing passwordsArgon2id, scrypt, bcrypt or PBKDF2, never the above
Authenticating a message with a secretHMAC-SHA-256

MD5 comes from RFC 1321 in 1992; SHA-256, SHA-384 and SHA-512 belong to the SHA-2 family standardized from 2001. SHA-3 uses a different internal construction and is not in the tool below, which offers MD5, SHA-1, SHA-256, SHA-384 and SHA-512. If an existing system uses MD5 only for de-duplication or cache keys with no attacker able to submit files, leaving it alone is fine. If inputs come from people you do not trust, move on: the change is usually a function name and a column that grows from 32 to 64 characters.

None of these store passwords

A password hash is meant to be slow. MD5 and SHA-256 are built to be fast, so an attacker with a leaked table tries billions of guesses per second on a GPU, and an unsalted fast hash also falls to precomputed lookup tables. Use a purpose-built scheme such as Argon2id, scrypt, bcrypt or PBKDF2, with a per-user salt, through a maintained library. Hashing a password with SHA-256 first does not fix this.

Keyed hashes and length extension

To authenticate a message with a secret, use HMAC. The tempting SHA-256(secret + message) is vulnerable to length extension: given the digest and the message length, an attacker can compute the digest of the message plus extra data without knowing the secret. This affects MD5, SHA-1, SHA-256 and SHA-512 but not the truncated variants such as SHA-384. HMAC removes the problem for all of them. The generator below computes plain digests and does not offer HMAC.

Hex or Base64 is the same digest

Hex and Base64 are two spellings of the same bytes. A SHA-256 is 64 hex digits or 44 Base64 characters ending in =. Browsers’ Subresource Integrity attribute uses the Base64 form, written like sha384-..., while most published checksums use hex, so the tool shows both side by side. Compare hex case-insensitively: A9993E36 and a9993e36 are the same value.

Hashing a file

sha256sum file.iso          # Linux
shasum -a 256 file.iso      # macOS
md5 file.iso                # macOS, MD5
Get-FileHash file.iso -Algorithm SHA256
certutil -hashfile file.iso SHA256

In the browser, crypto.subtle.digest('SHA-256', bytes) covers SHA-1 and the SHA-2 family but not MD5, and it only works on a secure origin (https or localhost). The tool computes MD5 with code in the page and the rest through that API, so on plain http you get MD5 and a notice that the others are blocked. File contents are read into memory in your tab and never uploaded, and it asks you to confirm before reading anything above 25 MB. If a file hash will not match the publisher’s, repeat the check on the original download, not on a copy that went through a mail client or a text editor.

Open the tool: Hash Generator & Checksum Calculator

Back to guides

More guides