Hash Functions Explained: MD5, SHA-1, SHA-256, and When to Use Each
Understand cryptographic hash functions: how MD5, SHA-1, SHA-256, and bcrypt work, why you should never use MD5 for passwords, and when each is appropriate in 2026.
Hash Functions Explained: MD5, SHA-1, SHA-256, and When to Use Each
What is a Hash Function?
A hash function converts input of any size into a fixed-length βfingerprint.β The same input always produces the same output. You cannot reverse a hash.
// Node.js
const crypto = require('crypto');
console.log(crypto.createHash('sha256').update('hello').digest('hex'));
// Output: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
console.log(crypto.createHash('md5').update('hello').digest('hex'));
// Output: 5d41402abc4b2a76b9719d911017c592
Comparison Table
| Algorithm | Output Length | Speed | Security | Use Case |
|---|---|---|---|---|
| MD5 | 128-bit | Fast | β Broken | File checksums (non-security) |
| SHA-1 | 160-bit | Fast | β Deprecated | Git commits (historical) |
| SHA-256 | 256-bit | Medium | β Secure | General-purpose hashing |
| bcrypt | Variable | Slow | β Secure | Password storage |
| Argon2 | Variable | Slow | β Best | Password storage (recommended) |
Why MD5 and SHA-1 Are Broken
// MD5 collision example (simplified concept)
// Two different inputs can produce the same hash
// This means an attacker can:
const maliciousFile = "malicious content";
const hash = md5(maliciousFile);
// If hash matches a legitimate file's hash, attacker wins
Practical risk: If your app uses MD5 for password hashing and your database leaks, attackers can look up the password in a rainbow table instantly.
Password Hashing β Never MD5
// β NEVER use MD5/SHA-256 for passwords (fast to brute force)
const hash = sha256(password);
// β
Use bcrypt (designed for passwords)
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12); // cost factor 12
// Verify
const match = await bcrypt.compare(password, hash);
// β
Best: Argon2 (winner of Password Hashing Competition)
const argon2 = require('argon2');
const hash = await argon2.hash(password);
When to Use Each
β SHA-256: File integrity checks, digital signatures, blockchain β bcrypt: Password storage (always use with a salt) β SHA-1: Git commit IDs (only for historical reasons) β MD5: Never for security (only for non-critical file checksums)
The Salt
// Always use a random salt when hashing passwords
const salt = crypto.randomBytes(16).toString('hex');
const hash = crypto.createHmac('sha256', salt).update(password).digest('hex');
// Store: salt + hash
But use bcrypt or Argon2 instead β they handle salting automatically.
Free Newsletter
Level Up Your Dev Workflow
Get new tools, guides, and productivity tips delivered to your inbox.
Plus: grab the free Developer Productivity Checklist when you subscribe.
Found this guide useful? Check out our free developer tools.
Affiliate disclosure: Some links below are affiliate links β we may earn a small commission at no extra cost to you. Learn more.
Recommended Tools & Resources
DigitalOcean
$200 credit for new users. Simple, affordable cloud hosting for developers.
GitHub Student Pack
Free access to 100+ developer tools. Perfect for students and new devs.
Vercel
Deploy frontend apps instantly. Free tier is generous for side projects.
DevPlaybook Products
Boilerplates, scripts & AI toolkits to 10x your dev workflow.