Hash Functions, Explained

After reading this you will know what a hash function does, why MD5 and SHA-256 produce the digests they do, why bcrypt gives a different result every time, and which algorithm to reach for in each situation.

What a hash function is

A hash function takes input of any length and returns a fixed-length string of bytes called a digest. Feed it one byte or one gigabyte, and the output size never changes. SHA-256 always returns 256 bits (32 bytes). MD5 always returns 128 bits (16 bytes). The mapping is deterministic: the same input produces the same digest every time, on any machine, in any language.

Here is the hook. The text hello hashed with SHA-256 is:

2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Change one character to hallo and the digest becomes:

d3751d33f9cd5049c4af2b462735457e4d3baf130bcbb87f389e349fbaeb20b9

Almost every hexadecimal digit changed. That property, where a tiny input change scrambles roughly half the output bits, is called the avalanche effect. It is what makes a digest useful as a fingerprint.

What the digests are good for

Hashes solve three practical problems.

Integrity checks
Publish the SHA-256 of a download. A reader who rehashes the file and gets the same 64 hex characters knows the bytes arrived intact.
Deduplication and cache keys
Two files with the same digest are almost certainly identical, so you can index them by hash instead of by content.
Password storage (with the right function)
Store a slow, salted hash of a password rather than the password itself. bcrypt is built for this; MD5 and SHA-256 are not.

MD5 and SHA-1 are broken for anything security-sensitive. Researchers can produce two different inputs with the same MD5 digest in seconds, and a full SHA-1 collision was demonstrated in 2017. Use them for checksums and cache keys only, never for signatures or passwords.

Why a plain hash is wrong for passwords

SHA-256 is fast. That is the problem. A modern GPU computes billions of SHA-256 hashes per second, so an attacker who steals your hash table can try billions of password guesses per second against it. Speed helps the attacker, not you.

Two other weaknesses make plain hashes worse:

  • No salt. Identical passwords produce identical digests, so an attacker sees which users share a password and can attack many accounts at once with a precomputed table.
  • No cost control. You cannot make SHA-256 slower as hardware gets faster.

bcrypt fixes all three. It adds a random salt, runs deliberately slowly, and lets you raise the cost as hardware improves.

The bcrypt cost factor

bcrypt has a tunable cost factor (also called work factor or rounds). The number of internal key-setup iterations is 2^{\text{cost}}, so each step up doubles the work.

\text{iterations} = 2^{\text{cost}}

Here cost is the integer you choose, typically between 10 and 14. At cost 10 bcrypt runs 2^{10} = 1024 iterations. At cost 14 it runs 2^{14} = 16384 iterations, which is 16 times more work than cost 10. If verifying one password takes about 60 milliseconds at cost 12, cost 13 takes about 120 ms and cost 14 about 240 ms.

The goal is to pick the highest cost your server can absorb during a login. A cost that makes one legitimate login take 200 ms makes an attacker's billion-guess campaign take years instead of hours.

Each increment of the cost factor doubles the iteration count, so the bar height doubles at every step from 1024 at cost 10 to 32768 at cost 15.

bcrypt cost 10 runs 1024 iterations; each step up doubles it. If cost 10 takes 15 ms to verify, cost 12 takes about 60 ms, cost 14 about 240 ms, and cost 16 about 960 ms. Higher cost slows attackers by the same factor it slows you.

Why bcrypt gives a different hash every time

Hash correct horse with bcrypt twice and you get two different outputs. This is not a bug. bcrypt generates a fresh 16-byte random salt on every call and stores it inside the output string. Because the salt differs, the digest differs, even though the password is identical.

A bcrypt hash string carries everything needed to verify it later:

$2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW

  1. $2b$ is the bcrypt version identifier.
  2. 12$ is the cost factor.
  3. The next 22 base64 characters (R9h/cIPz0gi.URNNX3kh2O) encode the 16-byte salt.
  4. The remaining 31 characters encode the 23-byte hash.

To verify a password, bcrypt reads the cost and salt out of the stored string, rehashes the candidate with those exact values, and compares. There is no separate salt column to manage; it travels with the hash.

Because the salt is random, you cannot compare two bcrypt hashes for equality to check if two passwords match. Always use the library's verify function, which extracts the salt and recomputes.

A worked example with the demo data

Load the tool with its defaults and hash the sample text. The plain hashes are deterministic, so you can reproduce every value below.

Hashing the word hello

Digests of the ASCII text hello (5 bytes)
AlgorithmOutput bitsHex lengthDigest (start)
CRC323283610a686
MD5128325d41402abc4b2a76b9719d911017c592
SHA-116040aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
SHA-256256642cf24dba5fb0a30e...
SHA-5125121289b71d224bd62f378...
  1. The hex length is always the bit length divided by 4, since each hex digit encodes 4 bits. SHA-256 gives 256 / 4 = 64 characters.
  2. CRC32 is not a cryptographic hash. It is an error-detecting checksum that returns a single 32-bit value, shown as 8 hex digits. Never use it for security.
  3. Rehashing hello a second time gives byte-for-byte the same result. These functions have no randomness.

If you need to know the exact byte count that goes into the hash (a hash operates on bytes, not characters), the String Length Inspector shows UTF-8 bytes versus characters. That distinction matters: café is 4 characters but 5 UTF-8 bytes, and the two encodings hash differently.

Reading and interpreting results

A few facts help you read any digest correctly:

  • Length is fixed by the algorithm, not the input. A one-character input and a novel both produce a 64-character SHA-256 digest.
  • Encoding matters. Hashing the bytes of a file differs from hashing its Base64 text. If your hash does not match a reference, check whether you hashed the raw bytes or an encoded form. The Base64 encoder-decoder helps you see the difference.
  • Case and whitespace count. A trailing newline changes every bit of the digest. Many mismatches come from an editor adding a final newline.

Common mistakes

To authenticate a message with a shared secret, do not concatenate the secret and text and hash them. That construction is vulnerable to length-extension attacks on MD5, SHA-1 and SHA-256. Use HMAC instead, which is built to resist it. See the HMAC Calculator.

  • Using MD5 or SHA-1 for signatures. Both are collision-broken. Use SHA-256 or better.
  • Using any fast hash for passwords. Use bcrypt, scrypt or Argon2.
  • Treating a hash as encryption. Hashing is one-way. There is no key that reverses SHA-256 back to the input. So-called "MD5 decrypters" are just lookup tables of previously computed hashes.
  • Hashing to shorten data safely. Truncating a 64-character hash to 8 characters multiplies collision risk enormously. Keep the full digest unless you have measured the collision math.

Related tools

Hashes rarely travel alone. To decode a token whose signature uses HMAC-SHA256, reach for the JWT Decoder. When you compare a digest length in bits against a file size, the Byte Size Converter keeps KB and KiB straight (a 256-bit digest is 32 bytes, not 256).

Frequently asked questions

Can you reverse a hash to get the original text?

No. Hash functions are one-way by design. Tools that claim to "decrypt" MD5 are matching your digest against a stored table of known inputs. Long or random inputs are not in any table, so they cannot be recovered.

Why does bcrypt produce a different hash each time but SHA-256 does not?

bcrypt adds a random 16-byte salt on every call and stores it in the output. SHA-256 has no salt and no randomness, so the same input always yields the same digest.

Which hash should you use for file integrity?

SHA-256 is the standard choice. It is fast, widely supported, and has no known collisions. Use SHA-512 if you want a larger digest, or CRC32 only for detecting accidental transmission errors, never tampering.

What bcrypt cost factor should you pick?

Pick the highest value that keeps a single verification near 100 to 250 ms on your hardware. That is often cost 12 to 14 today. Re-measure as servers get faster and raise the cost over time.

Is CRC32 a cryptographic hash?

No. CRC32 detects accidental bit errors in transmission or storage. An attacker can easily craft data with any CRC32 value you want, so it provides no security.