Convert MD5 to SHA-256? Why It’s Impossible (and What to Do Instead)
Plenty of pages promise to do it, and some of them look like working tools. The operation they advertise does not exist, and what you should do instead depends on why you wanted it.
The short answer: you can’t convert MD5 to SHA-256 (or SHA-256 to MD5)
No, and it is not a tooling gap that somebody will close later. An MD5 digest is 128 bits of output that does not contain the input that produced it. SHA-256 needs that input to compute anything at all. Without the original data the middle step is permanently missing, and no tool or library fills it in.
Here is the same input under three algorithms:
| Algorithm | Digest of hello | Hex chars | Bits |
|---|---|---|---|
| MD5 | 5d41402abc4b2a76b9719d911017c592 | 32 | 128 |
| SHA-1 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d | 40 | 160 |
| SHA-256 | 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 | 64 | 256 |
Look at the three digests as strings. They share no prefix and no substring, and no arithmetic turns one into another. The only thing connecting them is the word hello, and not one of them carries it. Compute them yourself with the MD5 hash generator and the SHA-256 generator if you want to watch both change independently as you type.
Direction makes no difference either. Going from SHA-256 to MD5 fails for exactly the same reason: both functions destroy information on purpose, so neither digest can be walked back to the input the other one would need.
Nobody types this query out of curiosity about hash theory. It comes from one of four tasks, and each has a real answer:
- Verifying a download or comparing checksums
- Migrating a password database off MD5
- Recovering the original input behind a hash
- Getting the same data hashed under a different algorithm
Before those, it helps to be able to spot a converter page for what it is.
What an “MD5 to SHA-256 converter” page actually does
There are only three possibilities, and none of them is a conversion.
Most of them ask you for the original text. You paste a string, the page produces both digests, and the marketing copy calls it a conversion. It is a hash generator with a misleading label. Nothing was converted; the input was hashed twice.
Some look the digest up. The page keeps a table of input-to-digest pairs harvested from wordlists and leaked credential dumps. Paste an MD5 whose input is in that table, and the page finds the input, then hashes it with SHA-256 and shows you the result. This works for password, 123456, and a long tail of other short strings. It fails silently on anything else, which is why these pages often return a blank result with no explanation.
A surprising number do nothing at all. They re-display your input, or emit a SHA-256 of the hex string you pasted while implying it is the SHA-256 of your original data. Those two values are different, and the section on double-hashing below shows exactly how different.
The test is quick. Give the page a 32-character hex string and nothing else, and ask whether it could possibly know the input. If it returns a 64-character result anyway and calls that a conversion, it is either querying a lookup table or lying to you. A hash converter that never asks for your original data has no way to be right except by coincidence.
The phrasing survives because it sounds like something adjacent that genuinely works: encoding.
Hashing, encoding, and encryption: only two of the three are reversible
Developers meet all three of these in the same week and file them in the same mental drawer. They behave completely differently:
| Operation | Example | Reversible? | What you need |
|---|---|---|---|
| Encoding | Base64, hex, URL-encoding | Yes, always | Nothing at all |
| Encryption | AES, RSA | Yes | The key |
| Hashing | MD5, SHA-1, SHA-256 | Never | Nothing helps |
Base64 is the one that trains the wrong intuition. Anyone can decode a Base64 string back to its bytes with no key and no permission, and converting Base64 to hex is a legitimate, everyday operation. Both are just alternative spellings of the same bytes. If you have seen that work, “MD5 to SHA-256” sounds like the same kind of re-spelling.
It is not. Encoding preserves every bit of the input, encryption preserves it behind a key, and hashing throws almost all of it away. An MD5 digest is 16 bytes no matter whether you fed it a password or a 40 GB disk image. The 40 GB did not go anywhere clever; it is gone. The MD5 tool’s FAQ covers the encryption comparison in more detail if you want it, but the one-line version is enough here: there is no key, so there is nothing to decrypt.
”MD5 is broken” does not mean “MD5 is reversible”
Even careful articles get this wrong, because people reason from “MD5 was broken years ago” straight to “so surely somebody can undo it by now.”
Two different attacks get mixed up here:
- A collision attack finds two different inputs that produce the same digest. The attacker chooses both inputs and does not care what they are.
- A preimage attack starts from a digest and recovers an input that produces it. This is the one that would let you convert MD5 to SHA-256, because it would hand you back something to feed into SHA-256.
MD5’s collision resistance fell in 2004, and today a collision can be constructed on ordinary hardware in seconds. That is why MD5 is unfit for signatures, certificates, and anything an adversary can influence.
MD5’s preimage resistance has not fallen. The best known preimage attack remains theoretical, with a complexity of 2^123.4 (Sasaki and Aoki, 2009). That is faster than brute force by a hair and unreachable by any margin that matters. Nobody is inverting arbitrary MD5 digests, in 2004 or now.
So the two facts sit side by side without contradiction: MD5 is broken, and MD5 is still not reversible. If you are choosing between the two algorithms for a new system rather than trying to convert between them, the MD5 vs SHA-256 comparison covers that decision properly.
The four tasks behind this search, and what to do for each
| What you are really doing | What to do instead |
|---|---|
| Verifying a download or comparing checksums | Recompute from the file with the algorithm you need |
| Migrating MD5 password hashes | Wrap them in bcrypt and upgrade on login |
| Recovering the original input | That is cracking, not converting, and it depends on entropy |
| Re-hashing the same data under another algorithm | Go back to the source bytes |
Task 1: You are comparing checksums or verifying a download
Recompute, do not convert. You have the file sitting on disk, which means you have the one thing the digest lost. Run whichever algorithm you need against it:
# GNU coreutils
md5sum ubuntu-24.04-desktop-amd64.iso
sha256sum ubuntu-24.04-desktop-amd64.iso
# macOS
md5 ubuntu-24.04-desktop-amd64.iso
shasum -a 256 ubuntu-24.04-desktop-amd64.iso
The mismatch people run into is a publisher who lists only an MD5 while your security policy demands SHA-256. Converting the published MD5 would prove nothing even if it were possible, because a digest you derived from another digest is not a statement by the publisher about the file. What you need is a SHA-256 that the publisher signed. If they do not offer one, computing your own SHA-256 with the SHA-256 generator still gives you a stable fingerprint for internal use: you can pin it, compare it across mirrors, and detect changes later. It just cannot substitute for the publisher’s attestation.
Task 2: You are migrating a password database off MD5
This is the task with the most at stake, and it has a well-worn solution: wrap the old hashes, then upgrade each account transparently at login. You bcrypt every stored MD5 hash in a single batch job, and from then on the login path MD5s the submitted password first and compares that against the bcrypt record.
One warning first, because a lot of older advice gets this backwards. Wrapping MD5 in SHA-256 does not make password storage safe. SHA-256 is a fast hash, the same category of problem as MD5, and GPUs chew through both at enormous rates. Advice that points you at a database’s built-in SHA2() function as the fix is solving the wrong problem. The target is a deliberately slow hash: bcrypt, scrypt, or Argon2. Store bcrypt(md5(password)), never sha256(md5(password)). The bcrypt vs Argon2 vs scrypt comparison covers how to pick among the three, and the bcrypt generator lets you test cost factors before you commit to one.
Now the part that actually breaks migrations. “The MD5 of the password” is ambiguous, and the two readings produce different results:
const { createHash } = require('node:crypto');
const md5Hex = createHash('md5').update('hello').digest('hex');
const md5Raw = createHash('md5').update('hello').digest(); // the same value as 16 bytes
createHash('sha256').update(md5Hex).digest('hex');
// 4914e23374bb211e3dca0df7636fefffc7fedd94f1340ae81c7d6c07b7113e9b
createHash('sha256').update(md5Raw).digest('hex');
// 88e20f0abb88153e3f0a9683668ccb5b84ed771817dc448a2b73254ed02c8d8c
createHash('sha256').update('hello').digest('hex');
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Three results, all correct, all different. Hash the 32-character hex string and you get one value; hash the 16 raw bytes it represents and you get another; hash the original password and you get a third. Pick a convention, write it down, and use the same one in the migration script and the login path. Getting this wrong locks out every user at once, and the symptom looks like a bcrypt bug rather than an encoding decision.
For a bcrypt wrapper, hex is the safer convention. Raw digest bytes can contain a zero byte, and several bcrypt implementations treat their input as a C string and stop reading there. Hex avoids that entirely, and at 32 characters it stays well under bcrypt’s input length limit. Normalize the case too, since 5D41402A... and 5d41402a... are different strings to bcrypt even though they are the same digest.
const bcrypt = require('bcrypt');
const { createHash } = require('node:crypto');
const legacyDigest = (password) =>
createHash('md5').update(password, 'utf8').digest('hex'); // lowercase hex
// Batch job, run once: wrap each stored MD5, then drop the old column.
async function wrapRow(row) {
return bcrypt.hash(row.md5_hash.toLowerCase(), 12);
}
// Login path
async function verify(password, row) {
if (row.scheme === 'bcrypt') {
return bcrypt.compare(password, row.hash);
}
const ok = await bcrypt.compare(legacyDigest(password), row.hash);
if (ok) {
const upgraded = await bcrypt.hash(password, 12);
await saveCredential(row.id, { scheme: 'bcrypt', hash: upgraded }); // your DB write
}
return ok;
}
Accounts move to plain bcrypt as their owners sign in. Set a deadline for the stragglers and force a reset after it.
Task 3: You are trying to recover the original input
Say so plainly, at least to yourself, because it changes the tooling and the expectations. Recovering an input from a digest is cracking, not converting, and whether it works has nothing to do with which algorithm produced the digest. It depends on the input.
Short, common, human-chosen strings fall quickly. Dictionary words, names with a digit on the end, and anything that has appeared in a breach corpus give way to a lookup or a short brute-force run. Long random strings do not fall at all, and the gap between the two cases is not a matter of buying more hardware.
The usual description of rainbow tables is too loose. A rainbow table recovers an input only when that input was hashed without a salt and is already present in the table. Both conditions are required. Add a per-user salt and the precomputed table is worthless, because the attacker would need a separate table per salt. Feed the hash a 128-bit random token and no table on earth contains it. The password entropy guide puts numbers on where the boundary sits.
If the input was a password you own and you cannot reproduce it, treat this as a reset, not a recovery. If it belongs to someone else, the honest framing is the one above.
Task 4: You need the same data hashed with a different algorithm (“md5 to sha1 converter”)
Same shape as Task 1, generalized. The pair of algorithms in the request does not matter, because the answer is always to go back to the source bytes and hash them again:
sha1sum payload.bin
sha256sum payload.bin
Every “md5 to sha1 converter” you find is a re-hasher or a lookup table, for the same reasons covered above. If the original data is gone, so is the answer. Pick the target algorithm with the SHA family comparison; the SHA-1 generator is there for legacy systems that still require it, though nothing new should.
The one case where a hash converter lookup actually works
Some classes of data are collected centrally and indexed by every common digest at once. Malware samples are the standard example. Services like VirusTotal store the sample itself, so they have computed its MD5, SHA-1, and SHA-256 from the same bytes and filed all three against one record. Search a sample’s MD5 there and you get its SHA-256 back.
That is a database join, not a conversion. It works because somebody had the original file and hashed it with every algorithm, exactly the recompute step described above, just done in advance by a third party. The conditions are strict: the object must already be in the index, and you have to trust whoever built it. Threat-intel workflows depend on this daily. It says nothing about arbitrary MD5 digests, and it will never help with a hash of your own data.
The mechanism is the same one the sketchy converter pages use. The difference is that a malware repository tells you it is a lookup and shows you the record.
Try it yourself
This is easier to see than to argue about. Hash the same string with both algorithms:
$ printf 'hello' | md5sum
5d41402abc4b2a76b9719d911017c592 -
$ printf 'hello' | sha256sum
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 -
Change one character and both outputs change completely, in ways that have nothing to do with each other. Paste the same text into the MD5 hash generator and the SHA-256 generator side by side to see it live, or reach for the HMAC generator when what you actually need is a keyed digest for signing an API request. All three run entirely in your browser.
FAQ
Can you convert MD5 to SHA-256?
No. An MD5 digest does not contain the original input, and SHA-256 needs that input to produce anything. Any page claiming to convert is either re-hashing text you supply or looking the value up in a database of precomputed pairs.
Why do so many sites offer an “MD5 to SHA-256 converter”?
They rank for a query people type. Once you land there, the page either asks for your original text, which makes it a re-hash rather than a conversion, or returns nothing useful. The demand is real even though the operation is not.
Is it possible to convert SHA-256 back to MD5?
No, and the direction does not matter. Both are one-way functions, so neither digest can be turned into the other without the original input. A tool offering the reverse trip is running the same lookup or re-hash trick.
MD5 is broken, so doesn’t that mean it can be reversed?
No. MD5’s collision resistance fell in 2004, meaning two inputs can be forced to share a digest. Reversing a digest is a preimage attack, and the best known one still costs 2^123.4 operations. MD5 is broken for signatures and still not invertible.
How do I migrate a database of MD5 password hashes to something safer?
In MySQL the obvious one-liner, UPDATE users SET password = SHA2(password, 256), is wrong — it hashes the stored MD5 digest rather than the password, so store bcrypt(md5(password)) and verify through the same wrapper, upgrading each record on the next successful login. Wrapping MD5 in SHA-256 does not help, because both are fast hashes and a GPU handles either at the same brutal rate.
Why did double-hashing give me a different result than expected?
Hashing the MD5 hex string and hashing its raw 16 bytes produce different SHA-256 outputs. Both are valid; they are just different inputs. Pick one convention and apply it identically in the migration script and the login path.
Can a rainbow table recover the input behind an MD5 hash?
Only when the input was unsalted and is already present in the table, which in practice means short or common strings. Long random inputs are not recoverable this way, and adding a per-user salt defeats precomputed tables entirely.
Is there an MD5 to SHA-1 converter?
No. Every “MD5 to SHA-1 converter” is a re-hasher or a lookup table, because the same one-way property blocks MD5 to SHA-1 exactly as it blocks MD5 to SHA-256. With the original input you can recompute it using the SHA-1 generator; without it, nothing can.