Cheatsheet

Hash Algorithms Comparison

# Hash Algorithms Comparison

A cryptographic hash turns arbitrary input into a fixed-size fingerprint. Not all hash functions are interchangeable — some are broken for security use but still fine for checksums, and "fast" is a security weakness for password hashing specifically. This sheet compares the common algorithms and says where each one actually belongs.

Quick reference

Output size and speed

Algorithm Output size Hex length Relative speed Status
MD5 128 bits 32 chars Very fast **Broken** — collisions practical since 2004
SHA-1 160 bits 40 chars Fast **Broken** — collisions demonstrated (SHAttered, 2017)
SHA-256 256 bits 64 chars Moderate Secure, industry standard
SHA-512 512 bits 128 chars Moderate (faster than SHA-256 on 64-bit CPUs) Secure
SHA-3-256 256 bits 64 chars Slower than SHA-2 in software Secure, different internal design (Keccak) than SHA-2
BLAKE2b Up to 512 bits (configurable) up to 128 chars Faster than SHA-2, faster than MD5 in many cases Secure
BLAKE3 256 bits default (extendable) 64 chars Faster than BLAKE2, parallelizable Secure

What each is actually for

Use case Right tool Wrong tool
File integrity checksum SHA-256, BLAKE3 MD5 (fine only for accidental-corruption checks, not tamper detection)
Git object IDs SHA-1 (the default everywhere, including GitHub/GitLab) SHA-256 repos are still an opt-in experimental git feature, not hosted in production by major forges
Password storage **bcrypt, scrypt, or Argon2** — never a raw hash SHA-256, MD5, SHA-512 alone
Message authentication HMAC-SHA256 A plain hash with no key
Digital signatures / TLS certs SHA-256 or stronger MD5, SHA-1 (both rejected by modern CAs and browsers)
Deduplication / content-addressing SHA-256, BLAKE3 MD5 (collision risk means two different files could map to the same key)

Common patterns

Hashing in Node.js

const crypto = require('crypto');
crypto.createHash('sha256').update('hello world').digest('hex');
// "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"

HMAC (keyed hash) for message authentication

crypto.createHmac('sha256', 'secret-key').update(payload).digest('hex');

Plain sha256(secret + payload) is not a substitute for HMAC — naive concatenation is vulnerable to length-extension attacks on some hash constructions; HMAC's nested construction is specifically designed to avoid that.

Verifying a hash without a timing side-channel

crypto.timingSafeEqual(Buffer.from(hashA), Buffer.from(hashB));

A plain === string comparison on secrets/HMACs can leak timing information about how many leading bytes matched — timingSafeEqual compares in constant time.

Correct password hashing (not a plain hash)

const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12); // cost factor 12
await bcrypt.compare(password, hash);

Password hashing needs to be deliberately slow and salted per-record — the opposite of what SHA-256/MD5 are optimized for.

Pitfalls

  • MD5 and SHA-1 are cryptographically broken, but still fine for non-adversarial checksums: "broken" means an attacker can craft two different inputs with the same hash (a collision) — that matters for signatures and tamper-detection, not for catching accidental file corruption during a transfer. Don't use either where a malicious actor could exploit a crafted collision.
  • Never hash passwords with a general-purpose hash function alone, salted or not: SHA-256 computes billions of hashes per second on commodity GPUs, which makes brute-forcing a stolen password database fast. bcrypt/scrypt/Argon2 are deliberately slow and memory-hard specifically to make that attack expensive.
  • A shorter hash isn't automatically faster to compute, and a longer one isn't automatically more secure against every attack: SHA-512 often runs faster than SHA-256 on 64-bit hardware (it's built around 64-bit word operations), despite producing double the output size.
  • Truncating a hash reduces its collision resistance faster than the truncated length suggests: cutting SHA-256 down to the first 64 bits doesn't give you "64-bit security" in general, but for collision resistance specifically it drops to roughly 32 bits of effective strength (the birthday bound), which is trivially breakable.
  • A hash is not encryption and can't be "decrypted": hashing is one-way by design. A UI or tutorial that says "decrypt this MD5 hash" really means "look it up in a precomputed table of hashes for common inputs" (a rainbow table) — it only works for common, unsalted, guessable inputs.

Related ZipKit tools

  • Hash Generator — compute MD5/SHA-1/SHA-256/SHA-512 (and more) for text or files, and compare two hashes.
  • JWT Decoder — JWTs are signed with HMAC-SHA256 (HS256) or an RSA/EC signature — inspect which algorithm a token actually uses.
  • KSUID Generator and ULID Generator — sortable unique IDs, a different tool than a hash for when you need identity, not a fingerprint of content.

Related cheatsheets

  • Base64 Reference — hash digests are frequently displayed Base64-encoded rather than as hex.
  • URL Encoding Reference — a hex or Base64 hash used in a URL path or query string still needs to follow these encoding rules.