Why do two tools give different hashes for the same thing?
Two programs, what you are certain is one input, and two digests that have nothing in common. The hash function is not the suspect — it is deterministic, and that is exactly why the disagreement is useful evidence. Six things cause it, the first accounts for about half, and three minutes with a byte count and a known test value tells you which one you have; Rocket Hash shortens the same investigation by putting all eight algorithms and the byte count on one screen.
You ran two tools over the same thing, asked both for SHA-256, and got two unrelated 64-character strings. Nothing is wrong with either program. A hash function is deterministic — the same bytes produce the same digest on any machine, in any language, in any decade — so two different answers are a reliable signal that the two tools were not given the same bytes, or were not computing the same function.
Note which way round the problem is, because it changes where you look. A collision is two different inputs sharing one digest — manufacturable on demand for MD5, demonstrated for SHA-1, never found for SHA-256, and in none of those cases something you walk into by accident. You have the opposite: one input that somehow produced two digests. That is a dull problem with a findable cause, and the cause is almost never exotic.
This page is for the case where you can run both tools yourself. If instead you have your own digest and a value a publisher printed on a web page, with no way to re-run their side, what to do when a checksum does not match ranks that situation's causes — most of which are about the download rather than about the tools.
Compare the two inputs by size before anything else. The cause at the top of the list below shows up as a difference of exactly one byte, and the byte count under the Text field puts that number on screen.
What a disagreement can and cannot mean
Change one bit of the input and the digest changes in about half of its bit positions, which in hexadecimal means fifteen characters in sixteen come out different. There is no sense in which two digests can be nearly equal, so you cannot read the size of the difference as the size of the cause — a missing newline and a completely different file look equally catastrophic on screen. The only information in a mismatch is that the inputs differed. Everything else you have to go and find.
Which means the whole investigation is one question asked repeatedly: what exactly went into each tool? Not what you meant to put in. What arrived.
The six causes, in order
Ordered by how often each one turns out to be the answer. The first two cover most of what you will ever meet.
| # | Cause | What gives it away |
|---|---|---|
| 1 | A trailing newline on one side | The byte counts differ by exactly one |
| 2 | The tools read different bytes | The file sizes differ, or one of them changed between runs |
| 3 | Line endings rewritten in transit | The sizes differ by roughly the number of lines |
| 4 | Text encoded differently | The byte count is far larger than the character count |
| 5 | Two functions with similar names | Same length, unrelated values — SHA-256 against SHA3-256 |
| 6 | One digest written in another notation | Same value, different alphabet, different length |
A trailing newline on one side
The newline is one byte, 0x0a, and it is invisible in every interface that matters. echo adds one; a here-string adds one; a text editor adds one at the end of the last line, usually without telling you; pressing Return before you stop typing adds one. A text field in a graphical tool does not.
So the three letters abc and a one-line text file holding those same three letters give two digests with nothing in common, because the file is four bytes where the string is three. That is not two tools disagreeing; it is two inputs, each hashed correctly. The byte count under the Text field says 3 or 4 before you have read a digest — hashing text on a Mac covers what that number catches.
The tools read different bytes
Obvious when you name it, and responsible for an embarrassing share of these. A folder with installer.dmg and installer (1).dmg in it. A .part or .download file whose real version finished arriving between your two runs. A path with a space in it that one tool interpreted as two arguments. An alias or symlink, where one tool follows the link and the other hashes the link itself. A cloud-storage placeholder that was a stub for the first tool and a real file for the second.
The general version of this is worse: if the file is being written while you read it, every pass over it is a different input and no two runs need agree. Logs, databases, anything being synced. Hashing a file that is still being written sets out the options. Before any of that, compare the sizes — two files of different lengths are two files, and the conversation is over.
Line endings rewritten in transit
Windows ends a line with two bytes, 0x0d 0x0a; macOS and Linux use one. Plenty of things helpfully convert between the two without mentioning it: a Git checkout with line-ending translation turned on, an FTP client in text mode, an editor with a default it applied on save, a copy-paste through a chat client.
When that happens the two files genuinely differ, and both digests are correct for the file each tool was given. The tell is arithmetic: a 400-line file converted from CRLF to LF is exactly 400 bytes smaller. This is also the commonest reason a source file hashes differently on a Mac and on a Windows machine — not the algorithm, not the tool, just the bytes.
Text encoded differently
A hash function takes bytes, so every tool that accepts text has to choose an encoding first, and they do not all choose the same one. UTF-8 is the normal answer and makes abc three bytes. UTF-16 makes it six, with alternating zeros. A byte-order mark adds three bytes at the front of a UTF-8 file that nothing displays. And an accented character has two valid spellings in Unicode — one code point or a letter followed by a combining mark — which look identical and are not the same bytes.
The byte count gives this away instantly: plain ASCII should cost one byte per character, and anything much larger is encoding rather than content. Unicode, emoji and invisible characters works through each case with the counts.
Two functions with similar names
Several pairs of different functions produce digests of identical length, which makes this the one cause that cannot be spotted by looking at the output.
- SHA-256 and SHA3-256. Both 64 hexadecimal characters, completely different constructions. If one tool means SHA-2 by “SHA-256” and another defaults to SHA-3, you will never get a match.
- SHA3-256 and Keccak-256. The same design with different padding. Ethereum tooling generally means the original Keccak; everything else means the standardized SHA-3.
- “SHA” and “SHA-2” as bare labels. “SHA” on its own usually means SHA-1, 40 characters; “SHA-2” usually means SHA-256, but not always.
- CRC32 variants. Different polynomials and bit orders travel under the same name, and macOS carries a
cksumof its own that is not the CRC a ZIP file stores. A decimal number such as1219131554where you expected eight hexadecimal characters —352441c2, forabc— is one of those variants, not damage.
Working out which algorithm a checksum uses deals with the ambiguous lengths, and what CRC32 is actually for explains why the CRC family is the worst offender for this.
One digest written in another notation
Sometimes the two values are the same digest and only the writing differs, which is worth ruling out before you go hunting for bytes. Hexadecimal may be upper or lower case; it may arrive in colon-separated pairs, as a fingerprint does; it may be grouped in fours for readability. And a digest is just as often given in base64, where SHA-256 becomes 44 characters instead of 64 — the SHA-256 of abc is ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=, the same 32 bytes the hex describes.
Interfaces that shorten a long digest in the middle cause the same confusion in a smaller way. Two values truncated at different points are not comparable, so copy the whole thing before you conclude anything.
How to prove which one it is
In this order, because each step is cheaper than the one after it.
- Count the characters of both values. Different lengths mean different algorithms, or one of them is base64, and no amount of re-reading the file will help.
- Give both tools a known input. The three letters
abchave a published digest in every algorithm. If the two tools agree onabcthey agree about the function, and your problem is the input. If they disagree onabc, the problem is the function or the tool. - Count bytes, not characters. For a string that is the count under the Text field; for a file it is the size in its row. This is the step that finds the newline, the byte-order mark and the line endings, and it takes seconds.
- Shrink the input. Make a three-byte file and hash it with both tools. Anything that survives a three-byte test case is a real difference in what the tools do, not a mistake in your setup.
- Bring in a third opinion. When two tools disagree, a third breaks the tie — and one that gives you several algorithms at once tells you which function the odd value came from.
Those middle steps are one screen in the app. Type the known input into Text and the byte count arrives under the field with all eight digests beneath it; for a file, the chevron at the end of its row in Files opens every algorithm from one pass over the disk.
For a string, the quickest third opinion is a browser tab: paste the same text into the SHA-256 generator and then into the SHA3-256 generator, and a value you had taken for a broken SHA-256 quite often turns out to be the SHA-3 of exactly the bytes you expected. Those pages hash text only, computed on your own machine with nothing uploaded. For a file the tie-breaker has to be something that can read the file off the disk, which is what Rocket Hash is for.
When one of the tools is genuinely wrong
It happens, and it is the last thing to suspect rather than the first. The failures that show up in real libraries are narrow: a package that labels Keccak as SHA-3, a web tool that converts text to bytes one character at a time and so mangles anything outside ASCII, an implementation that truncates a digest to fit a column, something that hashes the filename along with the contents.
Published test vectors settle it in one step. These are the values every correct implementation produces, and they do not depend on your file, your encoding or your shell:
| Function | Empty input | The letters abc |
|---|---|---|
| SHA-256 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad |
| SHA-1 | da39a3ee5e6b4b0d3255bfef95601890afd80709 | a9993e364706816aba3e25717850c26c9cd0d89d |
| MD5 | d41d8cd98f00b204e9800998ecf8427e | 900150983cd24fb0d6963f7d28e17f72 |
| CRC32, as ZIP uses it | 00000000 | 352441c2 |
Any tool that disagrees with the column on the right is wrong about something, and you have just found out which tool to stop using. Any tool that agrees is computing the function correctly, which means the remaining difference is in the bytes you fed it — and the six causes above are where it is hiding.
Troubleshooting
The two values differ only in capitalization
Then they are the same digest. Hexadecimal has no case: AB and ab are the same byte, and tools simply disagree about house style. Compare the two case-insensitively: a digest that differs only in case has not changed at all.
It matches on one Mac and not on another
The file differs, not the machine. Worth knowing what is not part of a digest: the filename, the folder, the permissions, the modification date, Finder tags and extended attributes are all outside the data being hashed, so none of them can change the answer. What does change it is something that rewrote the contents in transit — line-ending conversion, a re-created archive, a sync client that saved its own version.
The same tool gives a different answer twice
Then the file is moving underneath you. Check the size twice a few seconds apart: if it is growing, something is still writing, and every digest you take describes a file that no longer exists. Copy it somewhere quiet first, or wait for whatever is writing to finish.
Two tools disagree about a whole folder
Expected, and not a bug in either. A folder has no canonical digest, so any tool that offers one has invented a scheme: which files to include, whether to include hidden ones, what order to process them in, whether filenames are part of the input. Two schemes will never agree. Compare per-file digests instead — hashing a folder on a Mac explains why a manifest is the right shape for the job.
One tool only shows the beginning of the digest
Shortened display, not a shortened digest. The value on the clipboard is the full one, so copy both sides into the same plain text field and compare them there. If the copied values are different lengths, the shortening was in the copy rather than the display, and that is its own problem.
Frequently asked questions
Why do two tools give different hashes for the same file?
Because they were not given the same bytes, or not asked for the same function. A hash is deterministic, so identical input and identical algorithm always produce an identical digest. In practice the answer is a trailing newline, a file that is not quite the file you think, converted line endings, a different text encoding, or one tool computing SHA3-256 where the other computed SHA-256.
Why does my hash change when I re-create a zip file?
Because an archive is not its contents. A zip stores each entry's name and modification time alongside the compressed data, and the compressor's own choices affect the bytes too, so re-zipping an unchanged folder a minute later produces a different file and therefore a different digest. Hash the archive you actually shipped, or compare the files inside the two archives rather than the archives themselves.
Does a file's name, tags or modification date change its hash?
No. Hashing reads the contents of the file and nothing else, so you can rename a file, move it, change its permissions, add Finder tags or let the modification date change and the digest stays identical. That is what makes a digest useful as an identity for the data rather than for the file.
Why is the hash of my file different on Windows and on a Mac?
If the file was copied byte for byte it is not — the algorithms are identical everywhere. What usually happened is that something converted the line endings on the way across, turning each single 0x0a into the two bytes 0x0d 0x0a or back. A text file of 400 lines then differs by exactly 400 bytes, and both digests are correct for the file each machine holds.
Can two different files genuinely have the same hash?
Yes, and the word is a collision — but who can produce one deliberately is what matters. Collision resistance means nobody can find any two inputs sharing a digest; preimage resistance means that given a digest, nobody can find an input that produces it. They fail separately. MD5 lost collision resistance in 2004 and colliding files can now be made in seconds; SHA-1 lost it publicly in 2017, when the SHAttered work produced two different PDF files with one SHA-1. Both still resist preimage attacks, and no SHA-256 collision has ever been found.
How do I tell which of two tools is giving me the right hash?
Hash a known value with both. NIST publishes the answers: abc comes out as ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad under SHA-256, and an empty input as e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855. A tool that disagrees with those is wrong. A tool that agrees is correct, and your difference is in the input rather than the arithmetic.
Is a base64 hash different from a hex hash?
No — it is the same digest written in a different alphabet. SHA-256 produces 32 bytes, which is 64 characters in hexadecimal and 44 in base64. If one side gave you 44 characters ending in an equals sign and the other gave you 64 hexadecimal characters, convert one before concluding they disagree.