Skip to content
Free Tool Arena

How-To & Life · Guide · Developer Utilities

How to generate secure hashes

Hash function families, why MD5 and SHA-1 are broken for security, when they're still fine (checksums), salt/pepper for passwords, and HMAC.

Updated April 2026 · 6 min read

A cryptographic hash function takes any input and produces a fixed-length fingerprint that is (in theory) one-way: infeasible to invert, infeasible to find two inputs that collide. The “in theory” is doing a lot of work, because two of the hash functions still widely deployed — MD5 and SHA-1 — have had practical collisions published (MD5 in 2004, SHA-1 in 2017 by Google’s SHAttered attack). Using them for integrity or identity today is a known vulnerability. On top of that, hash functions are the wrong tool for passwords entirely — you want a deliberately slow password-hashing function like Argon2 or bcrypt. This guide covers which hashes are broken, which are current (SHA-256, SHA-3, BLAKE3), how collision and preimage resistance differ, the password-hashing family and why it is separate, salting and peppering, and the specific choice you should make in 2026.

Advertisement

What a hash function guarantees

A cryptographic hash function H maps an input of any length to a fixed-size output. The three security properties:

Preimage resistance: given H(x), infeasible to find x.

Second-preimage resistance: given x, infeasible to find a different x’ with H(x’) = H(x).

Collision resistance: infeasible to find any pair x, x’ with H(x) = H(x’).

Collision resistance is the hardest to maintain; it fails first when a hash weakens.

MD5 — broken; do not use

MD5 produces a 128-bit output. Collision attacks have been practical since 2004; in 2008 researchers forged a legitimate CA certificate using MD5 collisions. Modern GPUs can produce MD5 collisions in minutes.

Still acceptable for non-security uses: file chunking, cache-busting, non-cryptographic checksums where an attacker is not in the threat model. Never acceptable for digital signatures, certificates, integrity verification, or password hashing.

SHA-1 — broken for collisions

SHA-1 produces 160 bits. Theoretical attacks since 2005; Google’s SHAttered paper (2017) published a real collision, and follow-up work (Shambles, 2020) made chosen-prefix collisions practical at a cost of about $45,000 in GPU time.

Browsers stopped accepting SHA-1 certificates in 2017. Git still uses SHA-1 for object IDs; Linus has acknowledged the risk and the Git project is working toward SHA-256. Avoid SHA-1 for any new security-relevant use.

SHA-2 family — current standard

SHA-2 is a family: SHA-224, SHA-256, SHA-384, SHA-512, plus the truncated variants SHA-512/224 and SHA-512/256. Output in bits matches the number in the name.

SHA-256 is the default choice for most general-purpose hashing in 2026: file integrity, TLS certificates, Bitcoin addresses, content-addressed storage. No practical attacks.

SHA-512 is faster than SHA-256 on 64-bit CPUs and gives a larger output for use cases (HKDF, long-term archival) where the extra margin matters.

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

SHA-3 — different internal design

SHA-3 was standardized in 2015 (FIPS 202) as a structurally different alternative to SHA-2. It uses the Keccak sponge construction where SHA-2 uses Merkle–Damgård. Output sizes are the same: SHA3-224, SHA3-256, SHA3-384, SHA3-512.

Both SHA-2 and SHA-3 are secure in 2026. Use SHA-3 if you need diversification (don’t want all your security keyed on one construction surviving), or need the variable-output SHAKE128/SHAKE256. Otherwise SHA-2 has better hardware support and is slightly faster on most CPUs.

BLAKE2 and BLAKE3 — fast and modern

BLAKE2 (2012) is as secure as SHA-3 but much faster — often faster than MD5 on modern CPUs. Used by WireGuard, Argon2, and many content-addressed systems.

BLAKE3 (2020) goes further: it is parallelizable, incremental, and extendable-output. 10–20x faster than SHA-256 on typical hardware. No practical attacks. Adopted by Zcash, IPFS (alongside SHA-256), and content-addressed build tools.

For internal systems where you control both ends, BLAKE3 is a strong default. For interoperability with standards, pick SHA-256.

Passwords are different — use a KDF

Password hashing has opposite goals from file hashing. You want the function to be slow and memory-intensive, to resist the GPU clusters a stolen database will face.

Argon2id (winner of the 2015 Password Hashing Competition, standardized in RFC 9106) is the current recommendation from OWASP. Configure with t=3 iterations, m=12288 KiB memory, p=1 parallelism as a 2026 starting point.

scrypt (2009) is also memory-hard and well analyzed. Defaults of N=131072, r=8, p=1 are a good starting point.

bcrypt (1999) is older but still acceptable, especially when Argon2 is not available. Use a work factor of 12 or higher in 2026; 10 was fine in 2015, now too fast on modern GPUs. Note bcrypt truncates inputs at 72 bytes.

PBKDF2-HMAC-SHA256 with at least 600,000 iterations (OWASP 2023 guidance) is acceptable in regulated environments that require FIPS-approved primitives, but it is not memory-hard and loses to GPU attacks faster than the alternatives.

Salting

A salt is a unique random value added to the password before hashing. Defeats rainbow tables and ensures two users with the same password get different hashes.

Minimum salt length: 16 bytes of cryptographically random data. Generate per user, store alongside the hash. Argon2, bcrypt, and scrypt store the salt embedded in their output string — you do not need to manage it separately.

Peppering — optional additional layer

A pepper is a secret value, the same for every user, mixed in before hashing. Kept in application config, not in the database. If the database is stolen alone, the attacker still needs the pepper to brute-force.

Peppering does not substitute for slow hashing, but layers on top of it. Biggest gotcha: rotating the pepper invalidates every password hash. Use a versioned scheme: pepper_v2_value and store the version alongside the hash.

HMAC and keyed hashing

A plain hash cannot authenticate — anyone can produce H(message) since H is public. HMAC (HMAC(key, message)) fixes this. Used for API request signing, JWT HS256 tokens, and cookie integrity.

Most modern libraries expose hmac(key, message, 'sha256'). Both the message and key must be present on the verifying side. Use constant-time comparison when checking an HMAC (crypto.timingSafeEqual in Node) to avoid timing leaks.

Hash length and output representation

SHA-256 produces 32 bytes. Typical representations:

Hex: 64 characters. Human-readable.

Base64: 44 characters with padding, 43 without. More compact.

Base32: 56 characters. Case-insensitive; used in URLs.

Truncating a secure hash for ID purposes is safe down to about 128 bits (32 hex chars) for collision resistance given birthday-bound attacks. Never truncate below that for security-sensitive IDs.

Common mistakes

Hashing passwords with SHA-256. Any fast hash is a mistake for passwords. A commodity GPU computes billions of SHA-256 per second — an 8-character password falls in hours. Use Argon2id, scrypt, or bcrypt.

Missing salt. Identical passwords get identical hashes, rainbow tables work, single breach exposes whole columns of users. Always salt.

Reusing a salt across users. A shared salt is equivalent to no salt — rainbow tables can be rebuilt once against it. Fresh per-user.

Using MD5 for integrity. “It is just a checksum.” Not if an attacker can influence the file. Use SHA-256 or BLAKE3 for any integrity check that matters.

Comparing hashes with ==.String equality leaks timing information — attackers can binary-search the match position. Use constant-time compare.

Treating hashes as encryption. Hashes are one-way. There is no “decrypting” a hash. If you need to recover the original data, you need encryption (AES, ChaCha20), not hashing.

Run the numbers

Generate digests across MD5, SHA-1, SHA-256, SHA-512, and more with the hash generator. Pair with the password generator for the inputs those hashes will protect, and the UUID generator when you need unique non-sensitive IDs where a hash would be overkill.

Advertisement

Found this useful?Email