SHA-256: From Intuition to the Maths
See what SHA-256 is doing, then follow the padding, message schedule, and 64-round compression function step by step.
SHA-256 turns any message into a 256-bit number. The message can be a single letter, a photo, or a file with millions of lines. The result is always the same size: 256 bits.
You can think of that result as the message’s fingerprint. The same message always gives the same fingerprint. Change even one bit, though, and the new fingerprint should look unrelated to the old one.
This fingerprint is called a digest or hash. It is not an encrypted copy of the message. Encryption is meant to be reversed with a key; a hash is meant to be one-way.
For a well-designed 256-bit hash, trying to find a message with one chosen hash takes about 2256 guesses in the general case. Finding any two messages with the same hash takes about 2128 guesses because of the birthday effect. Those numbers are far beyond practical computing power.
Before looking at the equations, try changing either message below.
The avalanche effect
SHA-256 is loading…
SHA-256 is loading…
Each square is one output bit. Amber squares differ; dark squares match.
Only the last letter changed: abc became abd. Yet roughly half of the 256
output bits changed. This is the avalanche effect. SHA-256 creates it by
mixing the input again and again.
The rest of this article opens the machine. You do not need to memorize the equations. Read each one as a recipe: it tells us which values are mixed next.
The big picture
SHA-256 carries eight numbers as it works. Each number is 32 bits long, so the complete internal state is 8 × 32 = 256 bits:
The algorithm follows five steps:
- Convert the message to bytes.
- Add padding so its length is a multiple of 512 bits.
- Split it into 512-bit blocks.
- Mix each block into the eight-number state using 64 rounds.
- Join the final eight numbers to produce the 256-bit hash.
The state from one block becomes the starting state for the next block. This is why SHA-256 can process a huge file without loading the whole file into memory.
Step 1: make the message fit
The main SHA-256 function only accepts blocks of exactly 512 bits. Most messages do not naturally have that length, so SHA-256 adds padding.
Padding also stores the message’s original length. Without that length, inputs that end in zero bits could become ambiguous after padding.
Let ℓ be the original length in bits. SHA-256 appends:
- one
1bit; - enough
0bits to leave 64 bits at the end of the block; - ℓ, written as a 64-bit big-endian number.
If k is the number of zero bits, the padded message must satisfy:
k = (447 − ℓ) mod 512
Why 448? The last 64 bits are reserved for the original length, and 448 + 64 = 512.
Padding abc
In UTF-8, abc is three bytes:
61 62 63
Three bytes are 24 bits, so ℓ = 24. The first padding bit is 1. At
the byte level it appears as 80, which is 10000000 in binary. After enough
zeros, the final 64 bits store the number 24, or 18 in hexadecimal.
When the padded block is divided into sixteen 32-bit words, it looks like this:
That gives SHA-256 one complete 512-bit block to process.
The operations SHA-256 uses
From this point on, SHA-256 works with words. A word here simply means a 32-bit number.
| Notation | What it means |
|---|---|
x + y |
add the numbers modulo 232; overflow wraps around |
x ⊕ y |
XOR each pair of bits |
x ∧ y |
AND each pair of bits |
¬x |
flip every bit |
ROTRn(x) |
rotate right by n places; bits leaving the right side return on the left |
SHRn(x) |
shift right by n places; zeros enter on the left |
“Modulo 232” means that we keep only the lowest 32 bits after an addition. If the number becomes too large, it wraps around.
Rotation moves bits to new positions without losing them. XOR combines bit patterns. Addition creates carry bits, which lets one bit affect its neighbours. Together, these simple operations spread changes through the state quickly.
Step 2: turn 16 words into 64
Each block begins with sixteen 32-bit words, but SHA-256 runs 64 rounds. It needs one word for every round. It therefore expands the sixteen input words into a 64-word message schedule:
The first sixteen words come directly from the padded block. Starting at word 16, each new word is calculated from four older words:
The two small sigma functions rotate and shift their input in different ways:
σ1(x) = ROTR17(x) ⊕ ROTR19(x) ⊕ SHR10(x)
This schedule makes one changed input word affect many later rounds. The change does not stay in one small part of the calculation.
Step 3: mix the block 64 times
Before the first round, SHA-256 copies its eight state words into eight working variables named a, b, c, d, e, f, g, h.
It then uses four helper functions:
Maj(x,y,z) = (x ∧ y) ⊕ (x ∧ z) ⊕ (y ∧ z)
Σ0(x) = ROTR2(x) ⊕ ROTR13(x) ⊕ ROTR22(x)
Σ1(x) = ROTR6(x) ⊕ ROTR11(x) ⊕ ROTR25(x)
Ch means choose. Each bit of x chooses whether the result takes
the matching bit from y or z.
Maj means majority. For each bit position, it returns whichever bit—zero
or one—appears at least twice across x, y, and z.
The capital sigma functions rotate the same word by three different amounts and XOR the results. They move information between distant bit positions.
One round
Round t first calculates two temporary 32-bit values:
T2 = Σ0(a) + Maj(a,b,c)
Here, Wt is the current word from the message schedule. Kt is a fixed constant for this round.
Next, the eight working variables move one position, and the temporary values enter the state:
All additions still wrap modulo 232. This process repeats 64 times, using a new schedule word and a new constant in every round.
The 64 constants are public. They come from the fractional parts of the cube roots of the first 64 prime numbers. The eight starting state values similarly come from square roots of the first eight primes. They are fixed values, not secret keys.
The visualizer below performs the real SHA-256 calculation. It starts with the
padded abc block. Drag the slider to inspect one round, or press play to watch
all 64 rounds.
Inside the compression function
—
Kt—
T1—
T2—
—
b—
c—
d—
e—
f—
g—
h—
Values are hexadecimal. The state shown is immediately after the selected round.
Step 4: add the result back
After round 63, SHA-256 adds the working variables a through h back into the eight state words H0 through H7. Each addition wraps modulo 232.
This is called feed-forward. It combines the result of the 64 rounds with the state that entered the block.
If another 512-bit block remains, the updated state becomes that block’s input. After the last block, SHA-256 joins the eight state words:
The symbol ∥ means “join these values together.” For abc, the final hash is:
ba7816bf8f01cfea414140de5dae2223
b00361a396177a9cb410ff61f20015ad
The hash contains 64 hexadecimal digits. One hexadecimal digit represents four bits, so 64 × 4 = 256 bits.
Where the avalanche comes from
We can now connect the equations to the first demo:
- The message schedule carries each input change into many rounds.
- Rotations move bits to different positions.
- XOR combines several bit patterns.
- Addition creates carries, allowing one bit to affect nearby bits.
ChandMajmix three words at a time.- Feed-forward connects each block to everything processed before it.
After 64 rounds, the path from one input bit to one output bit is extremely tangled. There is no known practical shortcut for running that process backward or for controlling the final hash.
What SHA-256 is good for
SHA-256 is useful for checking whether data changed, identifying content, supporting digital signatures, and building other cryptographic systems.
But plain SHA-256 is not the right tool for every security problem:
- Passwords: SHA-256 is too fast. Use a slow, salted password hash such as Argon2id, scrypt, or bcrypt.
- Authenticating messages: use HMAC-SHA-256. A home-made construction such
as
SHA256(secret || message)can suffer from a length-extension attack. - Hiding data: use encryption. Hashing does not hide a message and provides no way to decrypt it.
- Checking a download: get the expected hash from a trusted source. If an attacker can replace both the file and its published hash, the check proves nothing.