Back to Blog
Security8 min read·September 11, 2026

Hash Generator Guide: MD5, SHA-1, SHA-256, and SHA-512 Explained

Learn about cryptographic hash functions — MD5, SHA-1, SHA-256, and SHA-512. Understand when to use each hash type and generate hashes online for free.

What a Hash Function Actually Guarantees

A cryptographic hash function takes an input of any length and returns a fixed-length digest. Feed it one byte or a 40 GB disk image and you get the same number of output bits.

Three properties matter, and separating them matters too, because algorithms break one at a time:

  • Preimage resistance — given a digest, you cannot find an input that produces it.
  • Second preimage resistance — given a specific input, you cannot find a different input with the same digest.
  • Collision resistance — you cannot find *any* two distinct inputs that share a digest.

Collision resistance is the cheapest of the three to attack, and in practice it falls first. By the birthday bound, an *n*-bit digest offers only about *n*/2 bits of collision resistance: SHA-256 gives 256-bit preimage resistance but roughly 128-bit collision resistance. Still far out of reach — but it explains why a 128-bit digest like MD5 was doomed before anyone found a practical attack.

One property hashes do not have is secrecy. A digest is not encryption: there is no key and nothing to decrypt. If the input space is small — a phone number, a four-digit PIN, a common password — anyone can hash every candidate and look yours up. "Hash decrypter" sites are precomputed lookup tables.

You can try all of this in the Hash Generator, which runs the algorithms in your browser so the input never leaves your machine.

The Four Algorithms Side by Side

AlgorithmDigest sizeHex charsSpecInternal designStatus in 2026

MD5128 bits32RFC 1321Merkle–Damgård, 512-bit blocksCollisions trivial; do not use for security
SHA-1160 bits40FIPS 180-4Merkle–Damgård, 512-bit blocksChosen-prefix collisions demonstrated; retired
SHA-256256 bits64FIPS 180-4Merkle–Damgård, 512-bit blocks, 32-bit words, 64 roundsSecure, the default choice
SHA-512512 bits128FIPS 180-4Merkle–Damgård, 1024-bit blocks, 64-bit words, 80 roundsSecure, often faster on 64-bit CPUs

SHA-256 and SHA-512 are not "the same algorithm at two sizes." SHA-512 works on 64-bit words over 80 rounds against SHA-256's 32-bit words over 64, so on a 64-bit CPU without hardware acceleration it often hashes bulk data *faster* than SHA-256 despite the longer digest. On chips with the SHA-NI extensions — which accelerate SHA-1 and SHA-256 but not SHA-512 — SHA-256 pulls ahead sharply. Benchmark rather than assuming bigger means slower.

SHA-384 and SHA-512/256 are SHA-512 with different initial values and truncated output — not truncations you can derive from a SHA-512 digest yourself.

One input through all four, to check any implementation you write:

Input:   hello

MD5: 5d41402abc4b2a76b9719d911017c592

SHA-1: aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

SHA-256: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

SHA-512: 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7

2323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043

The SHA-512 value is one continuous 128-character string, wrapped only to fit.

Generating Hashes in Code

Node.js exposes every algorithm the underlying OpenSSL build supports through crypto:

const crypto = require("crypto");

const fs = require("fs");

// One shot

crypto.createHash("sha256").update("hello").digest("hex");

// Streaming — the only sane way to hash a large file

const hash = crypto.createHash("sha256");

fs.createReadStream("installer.iso")

.on("error", (err) => console.error(err))

.on("data", (chunk) => hash.update(chunk))

.on("end", () => console.log(hash.digest("hex")));

A createHash object is single-use: after digest(), further update() calls throw ERR_CRYPTO_HASH_FINALIZED. Create a new one per file.

In the browser, Web Crypto covers SHA-1, SHA-256, SHA-384 and SHA-512. It deliberately omits MD5, so for that you must ship a library. crypto.subtle exists only in a secure context — HTTPS or localhost; on plain HTTP it is undefined:

async function sha256(text) {

const bytes = new TextEncoder().encode(text);

const buf = await crypto.subtle.digest("SHA-256", bytes);

return [...new Uint8Array(buf)]

.map((b) => b.toString(16).padStart(2, "0"))

.join("");

}

await sha256("hello"); // matches the SHA-256 value above

TextEncoder always emits UTF-8, so this agrees with the shell one-liners:

# Linux (GNU coreutils)

printf 'hello' | sha256sum

sha256sum ubuntu.iso

# macOS ships shasum, not sha256sum

shasum -a 256 ubuntu.iso

# Windows

certutil -hashfile ubuntu.iso SHA256

Note printf, not echo. Plain echo appends a newline, and hashing hello\n gives 5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03 — an entirely different digest. Almost every "the hashes don't match" bug is a stray newline or an encoding mismatch, not a broken algorithm.

MD5 and SHA-1 Are Broken, Concretely

"Broken" is vague, so here is what is actually true.

Practical MD5 collisions arrived in 2004 with Wang's differential attack; chosen-prefix collisions — the attacker picks two meaningful prefixes and appends colliding blocks — followed in 2007 and are now cheap. Flame used one in 2012 to forge a certificate chaining to a Microsoft Terminal Server licensing CA, letting it sign code Windows Update accepted.

SHA-1 fell in 2017, when the SHAttered research produced two different PDFs with the same digest. The 2020 "SHA-1 is a Shambles" work demonstrated a chosen-prefix collision for the price of a modest GPU rental. NIST has disallowed SHA-1 for digital signatures and set an end-of-2030 deadline for removing it from federal systems.

What this means in practice:

  • Never use MD5 or SHA-1 to prove a file came from who you think it did, to sign anything, or to deduplicate content an attacker can influence.
  • Preimage attacks on both remain infeasible. Neither is reversible; anyone recovering your input used a lookup table, not mathematics.
  • HMAC is a separate question. Its security proof does not rest on collision resistance, so HMAC-MD5 and HMAC-SHA1 are not broken by these attacks — but there is no reason to build anything new on a retired primitive.
  • Git still uses SHA-1 for object IDs, hardened with the collision-detection variant that rejects SHAttered-style inputs. A SHA-256 object format exists but adoption is slow. That is compatibility, not endorsement.

Verifying a Download End to End

This is the most common legitimate use of a hash, and most people do half of it. Run sha256sum installer.iso and compare the result against the publisher's SHA256SUMS file. A match means the bytes are intact — but an attacker who replaced the file on a mirror could replace the checksum list beside it, so a match alone only rules out corruption in transit.

The step people skip is verifying the *signature* on the checksum file:

gpg --verify SHA256SUMS.gpg SHA256SUMS

That chains the digest back to a key you trust. Digest alone gives integrity; digest plus signature gives authenticity.

Plain Hashes Are the Wrong Tool for Passwords

Guides still circulate recommending "SHA-256 plus a salt" for password storage. That advice is outdated.

The salt part is right: a unique random salt per user defeats rainbow tables and stops two users with the same password sharing a stored digest. The problem is speed. SHA-256 is engineered to be fast, and a single modern GPU computes it at billions of hashes per second. Salting does not slow that down; it only forces the attacker to work one account at a time.

Password hashing needs a function that is deliberately slow and memory-hungry:

  • Argon2id (RFC 9106) — the current recommendation. Tune memory, iterations and parallelism.
  • scrypt — memory-hard, a solid alternative where Argon2 is unavailable.
  • bcrypt — still acceptable. Watch its 72-byte input limit; longer passwords are silently truncated.
  • PBKDF2-HMAC-SHA256 (RFC 8018) — only when compliance demands it, at a high iteration count. Not memory-hard, so GPUs eat it.
const argon2 = require("argon2");

const stored = await argon2.hash(password, { type: argon2.argon2id });

const ok = await argon2.verify(stored, submittedPassword);

The library generates the salt and embeds it, with the parameters, in the stored string — you never manage them yourself. To gauge how much guessing work a password represents, the Password Strength Checker estimates entropy, and the Password Generator produces credentials with enough of it.

HMAC and the Length-Extension Trap

A common mistake is authenticating an API request by hashing secret and payload together:

// WRONG

const sig = crypto.createHash("sha256").update(secret + payload).digest("hex");

All four algorithms use the Merkle–Damgård construction, which publishes its full internal state as the digest. Given H(secret + payload) and the secret's length, an attacker can compute H(secret + payload + padding + evil) without ever learning the secret. That is a length-extension attack.

Use HMAC (RFC 2104), which nests two hash calls with keyed padding and is immune:

const sig = crypto.createHmac("sha256", secret).update(payload).digest("hex");

// Verify in constant time — never with ===

const received = Buffer.from(receivedSig, "hex");

const expected = Buffer.from(sig, "hex");

const valid =

received.length === expected.length &&

crypto.timingSafeEqual(received, expected);

timingSafeEqual throws if the buffers differ in length, which is why the length check comes first on untrusted input. Comparing with === short-circuits at the first differing byte, leaking the correct signature one byte at a time to anyone who can measure response times.

SHA-3, SHA-512/256 and BLAKE2 are not vulnerable to length extension, because none of them publishes its full internal state. That is a fair reason to pick one for a new protocol.

Choosing an Algorithm

Work down this list and stop at the first match:

  • Storing a password, or deriving a key from one → Argon2id, scrypt or bcrypt. Never a bare hash.
  • Authenticating a message with a shared secret → HMAC-SHA256.
  • Signatures, certificates, content addressing, anything adversarial → SHA-256, or SHA-512 for bulk data on 64-bit hardware.
  • Detecting accidental corruption only → SHA-256 is fast enough. CRC32 if you need raw speed and accept that it offers no security.
  • Cache keys over data nobody can influence → MD5 is defensible, but SHA-256 truncated to 128 bits costs little more.
  • Two habits worth keeping: record the encoding you hash — UTF-8 bytes, not "the string," since the same characters in UTF-16 give a different digest — and store the algorithm name beside every digest, so migrating later is a schema change rather than archaeology.

    For quick checks against a known-good value, the Hash Generator produces all four digests side by side. To inspect a signed token rather than a raw digest, the JWT Decoder shows the header algorithm and payload without sending it anywhere.

    #hash generator#md5#sha256#cryptographic hash#data integrity

    Try Our Free Online Tools

    100+ free tools for developers, designers, and everyone. No sign-up required.

    Browse All Tools