Home / Guides / Hash functions guide

Hash Functions Explained

What a hash function is, how MD5, SHA-1 and SHA-2 compare, what collisions and HMAC mean, and when to use which one, including why passwords are different.

Last updated

What a hash function is

A hash function reads data of any size and returns a short, fixed-size value, the hash or digest. You can think of it as a fingerprint of the data. The result of SHA-256 for the text hello is always the same 64 hex characters, whether the input is a word or a 4 GB file.

What makes a good cryptographic hash

  • Deterministic. The same input always gives the same hash.
  • Fast to compute for any input.
  • Avalanche effect. A one-bit change in the input changes about half of the bits of the hash.
  • Preimage resistance. Given a hash, nobody can find an input that produces it.
  • Collision resistance. Nobody can find two different inputs with the same hash.

A hash is not encryption. Encryption can be undone with a key, a hash cannot be undone at all.

The main algorithms

AlgorithmOutputHex lengthYearStatus
MD5128 bits321992Broken. Collisions are easy. Checksums only
SHA-1160 bits401995Broken for collisions. Being phased out
SHA-256256 bits642001Secure. The default choice
SHA-384, SHA-512384, 512 bits96, 1282001Secure
SHA-3 (Keccak)224 to 512 bits56 to 1282015Secure. A different design from SHA-2
BLAKE2, BLAKE3variablevariable2012, 2020Secure and very fast
CRC-3232 bits81975Not cryptographic. Error detection only

What a collision is, and why it matters

A collision is a pair of different inputs with the same hash. By the pigeonhole principle collisions must exist, but a good hash makes them impossible to find. When they become findable, an attacker can make a harmless file and a harmful one with the same hash, and a signature or checksum for one then also seems to fit the other.

  • MD5: practical collisions since 2004. In 2008 researchers made a fake certificate authority certificate, and in 2012 the Flame malware used an MD5 collision to forge a Microsoft certificate.
  • SHA-1: the first public collision, called SHAttered, came in 2017. Chosen-prefix collisions followed, which are the kind that break certificates. Browsers dropped SHA-1 certificates in 2017.
  • SHA-256 and SHA-512: no practical attack is known.

Passwords are a special case

A good password hash is deliberately slow, and that is the opposite of what a normal hash is built for. SHA-256 can be computed billions of times per second on a graphics card, so a stolen list of SHA-256 password hashes can be attacked quickly. Use an algorithm made for passwords:

  • Argon2id is the current recommendation of OWASP.
  • bcrypt is older, widely supported and still acceptable. Make one with the htpasswd bcrypt generator.
  • scrypt and PBKDF2 are also accepted when configured with enough work.

These add a random salt for each password, so that equal passwords give different hashes and lookup tables stop working. In PHP use password_hash() and password_verify(). Do not make up your own scheme from MD5 or SHA. For web server passwords see what is .htpasswd.

HMAC: hashing with a key

If you want to prove that a message is genuine, you cannot just hash key + message. With MD5, SHA-1, SHA-256 and SHA-512 that is open to a length extension attack, where someone who knows a hash can compute the hash of a longer message without the key. HMAC avoids this by hashing twice with the key mixed in. HMAC-SHA256 is used for API signatures, webhooks and the HS256 tokens of JWT. When you check a signature, compare it with a constant-time function such as hash_equals() in PHP or hmac.compare_digest() in Python.

What hashes are used for

  • Integrity checks of downloads and backups.
  • Digital signatures, which sign the hash of a document, not the document.
  • Content addressing. Git names objects by hash, and Docker names image layers by hash.
  • De-duplication and cache keys.
  • Blockchains and proof of work.
  • Message authentication with HMAC.

How to verify a downloaded file

# Linux
sha256sum file.iso
# macOS
shasum -a 256 file.iso
# Windows PowerShell
Get-FileHash file.iso -Algorithm SHA256

Compare the output with the checksum from the publisher, or drop the file on the file hash checker. A checksum on the same page as the download only protects you against accidents, not against a hacked site.

Hashing in code

LanguageSHA-256 of a string
JavaScript (browser)crypto.subtle.digest("SHA-256", new TextEncoder().encode(s))
Node.jscrypto.createHash("sha256").update(s).digest("hex")
Pythonhashlib.sha256(s.encode()).hexdigest()
PHPhash("sha256", $s)
JavaMessageDigest.getInstance("SHA-256").digest(bytes)
Gosha256.Sum256([]byte(s))

Common mistakes

  • Using MD5 or SHA-1 for signatures or for passwords.
  • Hashing passwords without a salt and without a slow algorithm.
  • Building a signature as hash(key + message) instead of using HMAC.
  • Comparing hashes with == instead of a constant-time function.
  • Getting different results because of encoding or line breaks: always hash bytes, and know which encoding made them.
  • Calling a hash encryption, or expecting to get the data back.

Frequently asked questions

What is a hash function?

A function that turns data of any size into a short fixed-size value. The same input always gives the same hash, and the input cannot be recovered from it.

What is the difference between MD5, SHA-1 and SHA-256?

They give 128, 160 and 256-bit hashes. MD5 and SHA-1 are broken for security use because collisions can be made. SHA-256 has no known practical attack.

Is hashing the same as encryption?

No. Encryption can be reversed with a key. A hash is one-way and has no key.

How should passwords be hashed?

With a slow, salted algorithm made for passwords: Argon2id, bcrypt or scrypt. In PHP use password_hash(). Do not use plain MD5, SHA-1 or SHA-256.

What is a hash collision?

Two different inputs that give the same hash. A good hash function makes them impossible to find. For MD5 and SHA-1 they can be made.

What is HMAC?

A way to use a hash with a secret key to prove that a message is genuine and unchanged. It avoids the length extension weakness of hash(key + message).