DEV Community

David
David

Posted on

MD5 vs SHA-1 vs SHA-256: A Developer's Guide to Hash Functions

You've seen hashes everywhere. Git commits. Password storage. File integrity checks. API signatures. But if someone asked you why SHA-256 and not MD5, could you explain it without Googling?

Let's walk through the hash function family — what each one does, when to use it, and when to absolutely not use it.


What Is a Hash Function?

A hash function takes input of any length and produces a fixed-length output. Always the same output for the same input. Always different for different inputs (in theory).

"hello"   → 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
"hello!"  → ce06092fb948d9ffac7d1a376e404b26b7575bcc11ee05a4615fef4fec3a308b
"hello"   → 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Enter fullscreen mode Exit fullscreen mode

Three properties matter:

  1. Deterministic — same input always gives same output
  2. One-way — you can't reverse-engineer the input from the output
  3. Avalanche effect — a tiny input change completely changes the output

The Big Three (+ Friends)

MD5 (Message Digest 5)

  • Output: 128 bits (32 hex characters)
  • Created: 1991, Ronald Rivest
  • Speed: Very fast
  • Status: ⚠️ Cryptographically broken
MD5("hello") → 5d41402abc4b2a76b9719d911017c592
Enter fullscreen mode Exit fullscreen mode

MD5 has known collision attacks — researchers can generate two different inputs that produce the same hash. In 2004, Xiaoyun Wang demonstrated practical collisions. In 2012, the Flame malware exploited MD5 collisions in Microsoft's code signing.

Use MD5 for: checksums, cache keys, non-security deduplication
Don't use MD5 for: passwords, digital signatures, anything security-related

SHA-1 (Secure Hash Algorithm 1)

  • Output: 160 bits (40 hex characters)
  • Created: 1995, NSA
  • Speed: Fast
  • Status: ⚠️ Deprecated, collisions found
SHA-1("hello") → aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
Enter fullscreen mode Exit fullscreen mode

Google and CWI Amsterdam produced the first practical SHA-1 collision in 2017 (the "SHAttered" attack). Git still uses SHA-1 internally but is migrating to SHA-256. Major browsers stopped accepting SHA-1 certificates in 2017.

Use SHA-1 for: legacy system compatibility, non-security checksums
Don't use SHA-1 for: anything new. Period.

SHA-256 (SHA-2 family)

  • Output: 256 bits (64 hex characters)
  • Created: 2001, NSA
  • Speed: Moderate
  • Status:Current standard
SHA-256("hello") → 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Enter fullscreen mode Exit fullscreen mode

No practical attacks known. Used in TLS, Bitcoin, code signing, and pretty much every modern security protocol. The SHA-2 family also includes SHA-384, SHA-512, and truncated variants.

Use SHA-256 for: file integrity, digital signatures, HMAC, data verification
For passwords: use bcrypt/scrypt/argon2 instead (see below)

SHA-3 (Keccak)

  • Output: Variable (224/256/384/512 bits)
  • Created: 2015 (standardized), Guido Bertoni et al.
  • Speed: Comparable to SHA-2
  • Status:Alternative standard
SHA3-256("hello") → 3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392
Enter fullscreen mode Exit fullscreen mode

SHA-3 uses a completely different internal structure (sponge construction) from SHA-2. It exists as a backup — if SHA-2 is ever broken, SHA-3 is ready with fundamentally different math.


Comparison Table

Algorithm Output Size Security Speed Use Case
MD5 128 bit ❌ Broken ⚡ Fastest Checksums, cache keys
SHA-1 160 bit ⚠️ Weak ⚡ Fast Legacy compat only
SHA-256 256 bit ✅ Strong 🔹 Moderate Signatures, integrity, HMAC
SHA-512 512 bit ✅ Strong 🔹 Moderate High-security applications
SHA-3 Variable ✅ Strong 🔹 Moderate Backup standard

Code Examples

JavaScript (Node.js)

const crypto = require('crypto');

const input = 'hello';

console.log('MD5:    ', crypto.createHash('md5').update(input).digest('hex'));
console.log('SHA-1:  ', crypto.createHash('sha1').update(input).digest('hex'));
console.log('SHA-256:', crypto.createHash('sha256').update(input).digest('hex'));
console.log('SHA-512:', crypto.createHash('sha512').update(input).digest('hex'));
Enter fullscreen mode Exit fullscreen mode

JavaScript (Browser — Web Crypto API)

async function sha256(message) {
  const encoder = new TextEncoder();
  const data = encoder.encode(message);
  const hash = await crypto.subtle.digest('SHA-256', data);
  return Array.from(new Uint8Array(hash))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

sha256('hello').then(console.log);
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Enter fullscreen mode Exit fullscreen mode

Python

import hashlib

text = "hello"

print("MD5:    ", hashlib.md5(text.encode()).hexdigest())
print("SHA-1:  ", hashlib.sha1(text.encode()).hexdigest())
print("SHA-256:", hashlib.sha256(text.encode()).hexdigest())
print("SHA-512:", hashlib.sha512(text.encode()).hexdigest())
Enter fullscreen mode Exit fullscreen mode

Bash (CLI)

echo -n "hello" | md5sum
echo -n "hello" | sha1sum
echo -n "hello" | sha256sum
echo -n "hello" | sha512sum
Enter fullscreen mode Exit fullscreen mode

Note: The -n flag is critical. Without it, echo adds a newline and you get a different hash.


Real-World Use Cases

1. File Integrity Verification

Download a file, compute its SHA-256, compare to the published hash:

sha256sum ubuntu-24.04-desktop-amd64.iso
# Compare with the hash on the download page
Enter fullscreen mode Exit fullscreen mode

2. Git Commits

Every Git commit is identified by a SHA-1 hash of the commit content (author, message, tree, parent):

git log --oneline
# a1b2c3d Fix authentication bug
Enter fullscreen mode Exit fullscreen mode

3. API Request Signing (HMAC)

Many APIs (AWS, Stripe webhooks) use HMAC-SHA256 to verify request authenticity:

const hmac = crypto.createHmac('sha256', secretKey);
hmac.update(requestBody);
const signature = hmac.digest('hex');
Enter fullscreen mode Exit fullscreen mode

4. Content-Addressable Storage

Systems like Docker and IPFS identify content by its hash — the same file always gets the same address:

sha256:e3b0c44298fc1c149afbf4c8996fb924...
Enter fullscreen mode Exit fullscreen mode

5. Subresource Integrity (SRI)

Browsers verify CDN scripts haven't been tampered with:

<script src="https://cdn.example.com/lib.js"
  integrity="sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE="
  crossorigin="anonymous"></script>
Enter fullscreen mode Exit fullscreen mode

The Password Exception

Never hash passwords with MD5, SHA-1, or even SHA-256 directly.

General-purpose hash functions are designed to be fast. That's exactly what you don't want for passwords — fast hashing means fast brute-forcing.

Use purpose-built password hashing functions:

Algorithm Why
bcrypt Built-in salt, configurable cost factor, battle-tested
scrypt Memory-hard (resistant to GPU attacks)
Argon2 Winner of Password Hashing Competition (2015), current best practice
// Node.js with bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash('mypassword', 12); // 12 rounds
const match = await bcrypt.compare('mypassword', hash); // true
Enter fullscreen mode Exit fullscreen mode

Quick Decision Guide

Need to hash a password?
  → Use Argon2 or bcrypt. Stop reading.

Need to verify file integrity?
  → SHA-256

Need to sign/verify API requests?
  → HMAC-SHA256

Need a fast cache key or dedup check?
  → MD5 is fine (no security needed)

Building something new with no legacy constraints?
  → SHA-256 as your default

Supporting a legacy system that uses SHA-1?
  → Plan your migration to SHA-256
Enter fullscreen mode Exit fullscreen mode

Try It Yourself

Need to quickly generate MD5, SHA-1, SHA-256, or SHA-512 hashes? hashgenerator.co computes all of them in real-time as you type — runs entirely in your browser, no data sent to any server.

Useful for verifying file checksums, generating test hashes, or just comparing outputs across algorithms side-by-side.


This is part of the Developer Tools Deep Dives series — practical guides to the tools and algorithms developers use every day.

Top comments (0)