When you have downloaded a Linux ISO, checked the “checksum” of a file, or looked inside an older password database, you have most likely encountered MD5. It produces a fairly short string consisting of 32 characters and was ubiquitous for decades.
MD5 today has an odd reputation. On one hand, it is described as “completely broken.” On the other hand, there are those who still employ it every day to check the integrity of files using their “checksums.” And both statements are true simultaneously, as the meaning of “broken” differs based on what purpose you are using the hash algorithm for.
The purpose of this article is to explain what MD5 is, its history, how it became broken, what still works fine about it, and what you should use instead.
What a hash function actually does
A cryptographic hash function accepts input of arbitrary length, like a password, a file, or even the entire image of a disk, and generates a fixed-size output known as a digest.
In case of MD5, this fixed size output is always 128 bits long or 32 hexadecimal digits (0-9 and a-f). For instance, MD5 of the string “hello” is
text
5d41402abc4b2a76b9719d911017c592
Hashing algorithms are supposed to have the following characteristics:
- Determinism: The input will always yield the same output.
- Speed: You will be able to hash a large file in a short time.
- Preimage Resistance: Given the digest, it must be practically impossible to obtain the original input.
- Collision Resistance: It must be practically impossible to get two different inputs with the same digest.
All of the above applies to MD5, but the tale of MD5 is that of the failure of one of the above qualities, collision resistance.
The history: from MD4 to RFC 1321
The MD5 was developed by Rivest of MIT and RSA Data Security. This follows the development of MD4, which was very fast, although it appeared to pose some cryptographic security risks. The MD5 came in 1991 as a more conservative alternative to MD4. MD5 was described as RFC 1321 in April 1992.
In the original description, it was said that “MD5 is slightly slower than MD4, but is more ‘conservative’ in design” and that MD4 was “at the edge” of risking a successful cryptanalytic attack. In effect, MD5 was intentionally designed to be somewhat slower to have a greater safety factor.
The MD5 was tailored for 32-bit processors. It requires no huge lookup tables, and its implementation code is quite compact. Such attributes made the MD5 algorithm spread rapidly in software applications during the 1990s.
In his description at that time, Rivest believed that it would be computationally infeasible to compute two messages having the same MD5 hash or to compute a message from a target hash value. Rivest’s belief turned out to be wrong.
How MD5 works, in plain terms
You don’t have to know how to create MD5 by yourself to get the hang of its architecture. Here is what it looks like:
MD5 is a Merkle-Damgard hash function that treats the input as a sequence of 512-bit blocks and mixes them into a 128-bit internal state. It works as follows:
- Padding: First of all, the input is padded with a 1-bit followed by 0s until its size becomes divisible by 512 bits, and 64-bit length is added at the end.
- Block hashing: The padded message is divided into 512-bit blocks and hashed along with the current state.
- Hashing: MD5 performs 64 rounds of bitwise arithmetic, modular addition, and left rotation on the message block and current state.
- Output: At the end of the block processing, the current 128-bit state will be the digest.
Since the same state is propagated across blocks, MD5 has an inherent weakness known as length extension: given MD5(message) and the length of message, it may be possible to find MD5(message||extra_data) without even knowing message. This becomes a problem when MD5 is used naively as a message authentication code as MD5(secret||message). The HMAC algorithm does not have this vulnerability due to its construction.
How did MD5 become broken? Collisions and timing.
The first cracks emerged quite early, but the real break did not occur until 2004.
1993-1996: initial warning signs. Some vulnerabilities in the compression function were discovered, and by 1996 there was even a collision, leading cryptologists to advise that MD5 be abandoned. It was just a warning, not yet an actual break.
2004: Wang et al. create a real collision. Xiaoyun Wang led a group that created an algorithm for finding collisions in MD5 between two separate inputs with the same MD5 digest. It was evidence of the failure of the collision resistance in MD5. The initial collision was an “identical-prefix” collision: pseudo-random 128-byte strings that differ in certain ways.
2006-2009: Chosen-prefix collisions and the rogue CA. The attacks became even more powerful. A chosen-prefix collision means that attackers can begin with two arbitrary, distinct prefixes to produce the final digests colliding. In 2008-2009, a group leveraged this attack to produce a rogue Certification Authority certificate, a certificate allowing the creation of fake HTTPS websites supposedly validated by a trusted CA. It was not a simple attack, yet it demonstrated that MD5-signed certificates should no longer be trusted.
2012: Flame malware. Flame malware used an MD5 chosen-prefix collision attack to get a code-signing certificate, seemingly issued by Microsoft’s Windows Update infrastructure.
2024: Blast-RADIUS. In July 2024, it was announced that Blast-RADIUS is a practical attack against the RADIUS/UDP authentication protocol. Responses in RADIUS are protected using an MD5-based authenticator, and the attackers were able to carry out a chosen-prefix collision attack within minutes, not days, thus being able to create a forged Access-Accept response. The same announcement mentioned earlier MD5-based attacks, such as SLOTH (2016), and a Windows certificate-verification bypass (2023).
The trend is obvious: while the ability to generate MD5 collisions started out as an academic exercise, it quickly became an attack vector, and the systems that continued to use MD5 suffered for it.
What “broken” actually means and what it does not
And that is why most beginning explanations of crypto fail.
MD5 is practically broken as regards collision resistance. Computing two files that collide under MD5 using standard computing equipment and proper tools is possible. The theoretical birthday bound for a 128-bit hash is roughly 2⁶⁴ evaluations, which is too small for contemporary computers; specialized attacks achieve a higher rate than the theoretical bound.
Yet, MD5 is not practically broken when it comes to preimage resistance. When given an MD5 hash value, computing any file that collides with it is impossible for a well-picked digest. No public attacks break down MD5 preimage resistance in the same manner that collisions were broken down. Thus, “MD5 can be reversed” is a mistake. The issue is that you cannot rely on two files being distinct due to their MD5 hashes differing, nor on any digital signature utilizing MD5 collision resistance.
This is an important distinction since it helps us understand how MD5 can continue to be used in certain non-secure scenarios. When all you need to do is check for any corruption in the files, an attacker cannot purposefully choose a colliding message; a corrupted message will almost never accidentally collide with an MD5 message. This is the reason why MD5 can continue to be used as a non-security checksum.
However, once an attacker gains control over the input, collision resistance becomes significant, and MD5 is no longer secure.
Where MD5 is still okay and where it is not
Reasonable (with conditions): non-security checksums. MD5 can still detect accidental corruption in transferring files or storing them. It is not the ideal choice. SHA-256 or non-cryptographic fast hashing like XXHASH3 is usually preferred, but MD5 can still serve as a checksum against accidental damage without involving security.
Legacy support. Some older protocols, systems, or file formats may require MD5. If you need to interoperate with them, you have no choice. In this situation, restrict the use of MD5 in a security context to legacy code and never extend it further.
Not acceptable: password storage. MD5 is a very poor password hash due to two different reasons. The first one is its speed; the algorithm was optimized specifically to perform fast, which is exactly what attackers want in their brute force attack on passwords. And the second reason is that MD5 does not include any salt by design, so the same passwords will generate the same hash values, and the precomputed hash-to-password table will allow an attacker to recover the passwords in no time.
Not suitable: digital signatures and certificates. According to RFC 6151, MD5 should not be used where collision resistance is required, such as in digital signatures. The National Institute of Standards and Technology (NIST) considers MD5 unsuitable for use from a security standpoint. The use of MD5 collision resistance in digital signatures would be insecure.
HMAC-MD5: nuance. According to RFC 6151, “The known attacks on HMAC-MD5 do not seem to indicate a practical vulnerability when used as a message authentication code.” Since HMAC’s construction does not resemble MD5 (secret || message) and length-extension does not work in the same way here, HMAC-MD5 is an older solution. Use HMAC-SHA-256 or another MAC if you design a new system.
Practical examples (illustrative, not tested here)
Below are some samples on how MD5 hashing is used. They were created for clarity purposes only and have not been run when writing this paper. They should be used only as starting points to test in your environment.
Command-line MD5 check in Linux/OSX:
bash
md5sum myfile.iso
On macOS, the command is usually md5 myfile.iso.
Verifying a downloaded file:
bash
md5sum -c myfile.iso.md5
This loads the checksum file and compares the two. If the two check sums match, then the file must be fine; otherwise, the file is either corrupted or has been modified.
MD5 Generation in Python (sample):
python
import hashlib
data = b"hello"
digest = hashlib.md5(data).hexdigest()
print(digest)
The output must be the 32 character hexadecimal number 5d41402abc4b2a76b9719d911017c592 when the input is b”hello”. It has not been run by me at all, so please try it yourself.
Reasons why you should not use this code for passwords: Same password always generates the same hash. An attacker, having a list of commonly used passwords, can hash them all and see whether the hashes match. The economics of the problem are totally changed by using salt and a slow algorithm.
What to use instead
Choosing the right successor depends on what purpose MD5 was being used for.
For integrity and file checksums: use SHA-256 or SHA-3. SHA-256 outputs a 256-bit hash and is available everywhere. Nowadays, on CPUs with hardware support for SHA, it may even outperform MD5 for speed, contrary to the old belief that MD5 is inherently faster. If you need non-cryptographic speed, use XXHASH3.
For password hashing: use Argon2id, scrypt, bcrypt, or PBKDF2 with proper settings. They are intentionally slow and use salt. Argon2id is recommended by OWASP and others as a default choice for new systems.
For message authentication: use HMAC-SHA-256 or any other modern AEAD scheme. Do not use MD5(key | message).
For digital signature: use SHA-256 or better. MD5 cannot be used in collision-resistant modes.
Takeaway #1
The first rule should not be “MD5 is bad.” The first rule should be:
There are hash functions with different security properties, and you should use the property that fits your task.
If the attacker can influence the inputs and collision resistance is essential for signing and authentication, MD5 is not secure.
when all you want is to protect against accidental corruption, MD5 could still work but SHA-256 would be a safer choice.
and if you use MD5 for password storage, then the issue is not collisions but speed and lack of salting.
Use MD5 when you actually need it, avoid it when you don’t and never make the same mistake again by equating security with 32-character string.
Also Explore Our Cybersecurity Category. And if you are reading it up to here, leave a sweet comment to motivate us to write blog everyday.



