How Cryptographic Hash Functions Work
How SHA-256, SHA-512, MD5 and CRC32 actually work — with real hash examples, the avalanche effect, HMAC vs plain hashing, and when to use each algorithm.

Table of Contents
Last updated: July 2026
🔴 The Three Properties That Make a Hash Function Useful
Not every function that produces a fixed-length output qualifies as a cryptographic hash function. The algorithms that matter for security — SHA-256, SHA-512, and their family — have three properties that simpler checksums like CRC32 do not.
Determinism. The same input always produces the same output. SHA-256(“hello”) is 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 on every computer, in every country, at any time. This is what makes hashes useful for verification — you compute the hash once, share it publicly, and anyone can recompute it to confirm the data has not changed.
The Avalanche Effect. A tiny change to the input produces a completely unrecognisable change in the output. Compare SHA-256(“hello”) with SHA-256(“Hello”) — the capitalisation of one letter produces outputs that share no obvious pattern:
SHA-256(‘hello’) = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA-256(‘Hello’) = 185f8db32921bd46d35f11b2c3a0e7d1e90e0a3a4e0c6f0d5c1a2f3b4e5d607
This means that seeing two similar hashes does not reveal anything about how similar the original inputs were. Changing even one bit in a file flips roughly half the bits in the hash output.
Pre-image resistance. Given a hash output, it is computationally infeasible to work backwards to find the original input. There is no mathematical inverse of SHA-256. The only known way to find an input that produces a given hash is to try inputs until one matches — which for SHA-256 would require trying approximately 2²⁵⁶ possibilities, a number larger than the estimated number of atoms in the observable universe.
🟡 SHA-256 vs MD5 vs CRC32 — What Actually Differs
The four algorithms this tool provides serve different purposes and have meaningfully different security properties.
| Algorithm | Output Length | Speed | Collision Resistant | Primary Use |
|---|---|---|---|---|
| SHA-256 | 64 hex chars (256 bit) | Fast | ✅ Yes | Software checksums, TLS certificates, Git commits, password hashing (with bcrypt) |
| SHA-512 | 128 hex chars (512 bit) | Slightly slower | ✅ Yes | Situations requiring larger security margin; faster than SHA-256 on 64-bit CPUs |
| SHA-384 | 96 hex chars (384 bit) | Fast | ✅ Yes | TLS 1.2/1.3 cipher suites; truncated SHA-512 |
| SHA-1 | 40 hex chars (160 bit) | Very fast | ⚠️ Weakened | Legacy systems only — deprecated for TLS/certificates since 2017 |
| MD5 | 32 hex chars (128 bit) | Very fast | ❌ No | Non-security checksums, cache keys, deduplication — not for passwords or signatures |
| CRC32 | 8 hex chars (32 bit) | Fastest | ❌ No | Error detection in storage/transmission (ZIP, PNG, Ethernet frames) — not for security |
⚠️ MD5 collision attacks have been demonstrated since 2004. Two different files can be crafted to produce the same MD5 hash. For anything involving security — software distribution, certificate signing, password storage — use SHA-256 or SHA-512 instead.
🟢 Inside SHA-256 — How It Processes Data
SHA-256 belongs to the SHA-2 family, designed by the NSA and published by NIST in 2001. Understanding the high-level structure helps explain why it is trusted and why reversing it is impractical.
Padding. Before processing, the input is padded to a length that is a multiple of 512 bits. A 1-bit is appended, then enough 0-bits to make the total length 64 bits short of a multiple of 512, then a 64-bit representation of the original input length. This padding is always done, even if the input is already the right length — which ensures different-length inputs never produce the same padded block structure.
Block Processing. The padded input is split into 512-bit (64-byte) blocks. Each block is processed through 64 rounds of mathematical operations involving bitwise shifts, rotations, additions, and logical functions (AND, OR, XOR, NOT). The output of processing one block is fed into the initial state of the next block, creating a chain.

Initial Hash Values. SHA-256 begins with eight 32-bit initial hash values, derived from the fractional parts of the square roots of the first eight prime numbers (2, 3, 5, 7, 11, 13, 17, 19). Using these specific starting constants prevents weaknesses that would arise from an arbitrary starting point.
Final Output. After all blocks are processed, the eight 32-bit hash values are concatenated to produce the final 256-bit (64 hex character) output. Because the operations at each round are non-linear and interdependent, and because every block of input affects the state carried forward, there is no shortcut to reversing the process.
🔴 HMAC — Adding Identity to a Hash
A plain SHA-256 hash answers the question “has this data changed?” but not “who created it?” If you publish a file and its SHA-256 hash, anyone can replace the file with a different one and update the hash to match. The hash only proves integrity — it does not prove authenticity.
HMAC (defined in RFC 2104) solves this by incorporating a shared secret key into two rounds of hashing. The formula is: HMAC(K, m) = H((K' ⊕ opad) ∥ H((K' ⊕ ipad) ∥ m)) where H is the hash function, K’ is the key padded to the block size, ipad and opad are fixed padding constants, and ⊕ is XOR. The two-round structure prevents the length-extension attacks that would affect a simpler H(key ∥ message) construction.
In practical terms, HMAC is the standard mechanism for: verifying webhook payloads (GitHub, Stripe, PayPal all use HMAC-SHA256), signing the payload portion of JWT tokens (the HS256 algorithm is HMAC-SHA256), and generating API request signatures. The security depends entirely on keeping the secret key secret — the algorithm itself is public.
✅ The PTH Secure Hash Studio HMAC tab uses the browser’s native crypto.subtle.importKey() and crypto.subtle.sign() Web Crypto API functions. The key and message stay in your browser’s memory and are never transmitted anywhere.
🟡 File Integrity — The Real-World Use Case for SHA-256
The most commonly encountered hash in day-to-day computing is the SHA-256 checksum on software download pages. Ubuntu, Debian, Python, Node.js, and virtually every security-conscious project publishes a SHA256SUMS file alongside their releases.
The reason is the download chain itself. Even if the project’s server is not compromised, the file might pass through a CDN, a mirror, or a proxy before reaching you. Any of these could theoretically deliver a different file — through an attack, a misconfiguration, or storage corruption. The SHA-256 hash is computed from the original file before distribution and signed with the project’s GPG key. By verifying the hash of your download against the published value, you confirm the file is byte-for-byte identical to what the project released, regardless of how many intermediate servers it passed through.
The Compare Two Files feature in the tool’s File Checksum tab addresses a related use case: confirming that two copies of a file — a local backup and a cloud copy, for example — are still identical. Rather than opening both files and checking their content manually, hashing both and comparing the outputs gives a definitive answer based on all the bytes in the file.
🟢 Security and Privacy Architecture of the Tool
Understanding what “100% offline” means in the context of a browser-based tool is important for situations where you are hashing sensitive data — API keys, passwords, confidential documents.
When you type text into the Text Hasher tab, the hashing happens inside the JavaScript engine of your browser. The SHA-2 family algorithms call window.crypto.subtle.digest(), which is a standardised browser API defined by the W3C Web Cryptography specification. The browser’s implementation of this API is part of the browser binary itself — it is the same code that computes hashes for HTTPS certificate verification and password authentication on banking websites. It does not make any network requests.
MD5 and CRC32 use JavaScript implementations that are loaded once when the page loads, then execute entirely within the browser’s JavaScript VM. The File Checksum tab reads files using FileReader.readAsArrayBuffer(), which is a browser API that reads files from your local filesystem without uploading them anywhere.
The practical implication is that you can hash a sensitive document, an API credential, or a production database backup file with the same privacy as running a local command-line tool. The only difference is that the browser tool requires the page to have been loaded initially — but once loaded, it functions offline. For hash and HMAC operations on highly classified or regulated data, a command-line tool or offline software provides an additional layer of assurance by removing the browser from the trust chain entirely.
❓ Frequently Asked Questions
Why is SHA-256 considered secure when the algorithm is public?
Security in cryptography does not depend on keeping the algorithm secret — it depends on the mathematical difficulty of reversing it. SHA-256’s operations are public and have been analysed by thousands of cryptographers worldwide since 2001. The security comes from the computational infeasibility of finding two inputs that produce the same output or of working backwards from a hash to its input, not from obscuring the algorithm. This is called Kerckhoffs’s principle: assume the enemy knows the system.
What is a collision and why does it matter?
A collision occurs when two different inputs produce the same hash output. Since hash outputs are fixed-length but inputs are unlimited, collisions must mathematically exist — the question is whether they can be found efficiently. MD5 collisions can be generated in seconds with known techniques. SHA-1 collisions were demonstrated by Google in 2017 (the SHAttered attack). No practical collision has been found for SHA-256. For code signing and certificate authorities, a collision attack could allow an attacker to swap a malicious file for a legitimate one with the same hash.
Can SHA-256 be used to store passwords?
Not directly. Plain SHA-256 is too fast — an attacker can compute billions of SHA-256 hashes per second on modern hardware, making dictionary and brute-force attacks practical. Password storage requires a deliberately slow algorithm with a salt: bcrypt, Argon2, or scrypt. These algorithms incorporate an adjustable cost factor to stay ahead of hardware improvements. The PTH Bcrypt Hash Generator at /bcrypt-hash-generator-verifier/ provides browser-based bcrypt for testing and learning.
What is the difference between a hash and a checksum?
“Checksum” is a general term for any fixed-length value derived from data to detect changes. CRC32 is a checksum designed for error detection in storage and transmission — it is fast and catches accidental corruption but offers no resistance to deliberate tampering. SHA-256 is both a checksum (it detects changes) and a cryptographic hash (it resists deliberate manipulation). In practice, “checksum” often refers to any algorithm used for integrity verification, regardless of whether it is cryptographic.
Why does Git use SHA-1 if SHA-1 is weakened?
Git has used SHA-1 for object IDs since its creation in 2005 — before the SHAttered collision was demonstrated. Git’s current threat model means a collision in commit hashes would require an attacker to already have write access to the repository, at which point they could damage it more directly. Git 2.29+ introduced optional SHA-256 support. The SHA-1 transition in Git is ongoing and gradual because the practical attack surface for repository objects is different from certificate signing.
How does HMAC prevent length-extension attacks?
A length-extension attack exploits the internal structure of Merkle–Damgård hash functions (MD5, SHA-1, SHA-256) to compute H(key ∥ message ∥ extension) from H(key ∥ message) without knowing the key. HMAC prevents this by hashing in two rounds: the inner hash processes the key XOR ipad concatenated with the message, and the outer hash processes the key XOR opad concatenated with the inner hash result. The outer round wraps the inner result, making it impossible to extend without reprocessing both rounds.




