How does a message of any length become a 32-byte digest? In SHA-256, its bytes pass through a small set of operations, repeated enough times that each part of the input can influence the whole result.

We will follow that calculation in four stages: prepare the bytes → expand the message → mix the state → assemble the digest. SHA-256 is our concrete example; Keccak-256 ⁠, used by Ethereum, follows a different construction.

Everything becomes bytes

Text is encoded, files are read, and structured objects are serialized. By the time data reaches SHA-256, it is a sequence of bytes. The hash calculation does not need to know which format it came from.

Source formats → byte sequence → SHA-256TextUTF-8 encodeImage / audioRead file bytesFileRead file bytesObject / transactionSerializeRaw bytesUse directlyByte sequence61 62 63 64 …Variable lengthSHA-256Pad → MixDigest32 bytes

These paths produce the same kind of representation, not identical content. An image file's bytes include its format and metadata; hashing a decoded image is a different choice. Structured data needs an agreed serialization so the same object produces the same bytes.

Drag the length slider to follow a shorter or longer input through every step. The sample repeats the letters a–z, one UTF-8 byte per letter. The length is measured before padding; zero means an empty input. All length controls below share this same input. The byte preview pairs each letter with its hexadecimal value. Every interactive figure labels the current input; reset returns to abc.

Input · abc · 61 62 63
Input length3 B
a61
b62
c63

Make complete blocks

SHA-256 reads 64 bytes at a time. Before processing, it adds an ending that makes the message fill a whole number of blocks.

For a byte-aligned message, append 80, enough zero bytes, and finally eight bytes recording the original bit length. The 80 byte is a 1 bit followed by seven zeros; it marks where the message ends. The length field records how long the original message was.

Each position below is one byte. Dark circles show the actual input bytes in hex. The blue-violet marker is 80, hollow dots are zero padding, and the final eight outlined cells encode the original bit length, most-significant byte first. The shaded outline groups all padding, including the length field. Each block holds 64 bytes.

Input · abc · 61 62 63
Input length3 B
Byte 0: 6161Byte 1: 6262Byte 2: 6363Byte 3: 8080Byte 4: 00Byte 5: 00Byte 6: 00Byte 7: 00Byte 8: 00Byte 9: 00Byte 10: 00Byte 11: 00Byte 12: 00Byte 13: 00Byte 14: 00Byte 15: 00Byte 16: 00Byte 17: 00Byte 18: 00Byte 19: 00Byte 20: 00Byte 21: 00Byte 22: 00Byte 23: 00Byte 24: 00Byte 25: 00Byte 26: 00Byte 27: 00Byte 28: 00Byte 29: 00Byte 30: 00Byte 31: 00Byte 32: 00Byte 33: 00Byte 34: 00Byte 35: 00Byte 36: 00Byte 37: 00Byte 38: 00Byte 39: 00Byte 40: 00Byte 41: 00Byte 42: 00Byte 43: 00Byte 44: 00Byte 45: 00Byte 46: 00Byte 47: 00Byte 48: 00Byte 49: 00Byte 50: 00Byte 51: 00Byte 52: 00Byte 53: 00Byte 54: 00Byte 55: 00Byte 56: 0000Byte 57: 0000Byte 58: 0000Byte 59: 0000Byte 60: 0000Byte 61: 0000Byte 62: 0000Byte 63: 1818
Length · 24 bits
Input 3 BPadding 61 B

Move the input slider between 55 and 56 bytes. At 55, the ending fits in one block: 55+1+8=6455+1+8=64. At 56, it spills into a second block. At 64 input bytes, the message fills a block exactly, so its ending needs a new block of its own.

The padding equation

For an original bit length ℓ\ell, append one 1 bit and the smallest nonnegative number kk of zero bits such that:

ℓ+1+k≡448(mod512)\ell+1+k\equiv448\pmod{512}

Append the 64-bit encoding of ℓ\ell to reach a multiple of 512 bits.

Work in small words

Split each 64-byte block into sixteen words, each four bytes long. A word is just a 32-bit number. Read the most significant byte first, so 61 62 63 80 becomes the word 61626380.

SHA-256 uses a few operations on these words:

  • Add: keep the low 32 bits if the result overflows. For example, ffffffff + 00000001 = 00000000.
  • XOR: compare corresponding bits; output 1 when they differ.
  • Rotate or shift: move bits to different positions. Rotation wraps them around; a shift discards them and fills with zeros.
Rotate / shift · fixed 8-bit example
Right 1
InOut716050413020110110010011

This illustration uses a fixed eight-bit value, independent of the message, so the movement is easy to see. SHA-256 does the same operations on 32 bits.

Rotations move an input bit to other positions. Addition brings in carries: even 0111 + 0001 = 1000 changes several bits. Combining these operations lets a local difference spread as the computation proceeds.

We will write XOR as ⊕\oplus and wrapping addition as ⊞\boxplus:

x⊞y=(x+y) mod 232x\boxplus y=(x+y)\bmod 2^{32}

Expand the message

Each block goes through 64 rounds, and each round needs one message word. We have sixteen words so far. To get the remaining 48, SHA-256 repeatedly combines four earlier words.

Call the word for round tt WtW_t. The first sixteen come straight from the selected block, four bytes per word. They include padding bytes when those fall inside the block.

From word 16 onward:

Wt=σ1(Wt−2)⊞Wt−7⊞σ0(Wt−15)⊞Wt−16W_t=\sigma_1(W_{t-2})\boxplus W_{t-7} \boxplus\sigma_0(W_{t-15})\boxplus W_{t-16}

The two σ\sigma functions mix a word by XORing rotated and shifted copies of it. Two of the four earlier words pass through these functions; the other two enter the sum unchanged.

Input · abc · 61 62 63
W[16]
σ₁(W[14])00000000
W[9]00000000
σ₀(W[1])00000000
W[0]61626380
W[16]61626380Sum mod 2³²

Move the word slider to see which four earlier words contribute. Change the input length or the selected block to follow a different calculation. This is the message schedule: it keeps reintroducing the input in different combinations across the rounds. It creates dependencies, not extra information.

Exact rotation and shift amounts

ROTR⁡r(x)\operatorname{ROTR}_r(x) rotates right by rr bits; SHR⁡r(x)\operatorname{SHR}_r(x) shifts right and fills with zeros.

σ0(x)=ROTR⁡7(x)⊕ROTR⁡18(x)⊕SHR⁡3(x)σ1(x)=ROTR⁡17(x)⊕ROTR⁡19(x)⊕SHR⁡10(x)\begin{aligned} \sigma_0(x)&=\operatorname{ROTR}_7(x)\oplus\operatorname{ROTR}_{18}(x)\oplus\operatorname{SHR}_3(x)\\ \sigma_1(x)&=\operatorname{ROTR}_{17}(x)\oplus\operatorname{ROTR}_{19}(x)\oplus\operatorname{SHR}_{10}(x) \end{aligned}

These fixed amounts are part of SHA-256's design.

Mix eight working words

Alongside the message schedule, SHA-256 keeps eight working words named a,b,c,d,e,f,g,ha,b,c,d,e,f,g,h. Together they hold 256 bits. Think of them as eight slots whose contents change every round.

The first block starts with eight fixed values. Each round reads one schedule word WtW_t and a fixed round constant KtK_t, then computes two temporary values:

T1=h⊞Σ1(e)⊞Ch⁡(e,f,g)⊞Kt⊞WtT2=Σ0(a)⊞Maj⁡(a,b,c)\begin{aligned} T_1&=h\boxplus\Sigma_1(e)\boxplus\operatorname{Ch}(e,f,g)\boxplus K_t\boxplus W_t\\ T_2&=\Sigma_0(a)\boxplus\operatorname{Maj}(a,b,c) \end{aligned}

There are three small ideas inside these equations. Σ\Sigma mixes bit positions using rotations and XOR. Choose, Ch⁡\operatorname{Ch}, uses each bit of ee to select a bit from ff or gg. Majority, Maj⁡\operatorname{Maj}, takes whichever bit appears at least twice among a,b,ca,b,c.

The update is simpler than the equations suggest: six words move to the next slot; two receive newly mixed values.

anew=T1⊞T2,enew=d⊞T1a_{\text{new}}=T_1\boxplus T_2, \qquad e_{\text{new}}=d\boxplus T_1
Input · abc · 61 62 63
Round 0
BeforeAfterT₁ + T₂d + T₁a6a09e667a5d6aebcdbbb67ae85b6a09e667c3c6ef372cbb67ae85da54ff53ad3c6ef372e510e527fefa2a4622f9b05688cf510e527fg1f83d9abg9b05688ch5be0cd19h1f83d9ab
Round arithmeticT₁ = 54da50e8 · T₂ = 08909ae5a′ = 54da50e8 + 08909ae5 = 5d6aebcde′ = a54ff53a + 54da50e8 = fa2a4622

The arrows show where each new value comes from. All eight updates use the old state. The message enters through T1T_1, affects both aa and ee, then moves through the other slots in later rounds.

Expand “Round arithmetic” to see the two additions for the selected round. The next round repeats the same rule with the updated state and the next schedule word. After 64 rounds, all eight words have been repeatedly mixed.

Boolean functions and constants

Here ∧\land means bitwise AND and ¬\neg flips all 32 bits. Choose and majority operate independently at each bit position:

Ch⁡(x,y,z)=(x∧y)⊕(¬x∧z)Maj⁡(x,y,z)=(x∧y)⊕(x∧z)⊕(y∧z)\begin{aligned} \operatorname{Ch}(x,y,z)&=(x\land y)\oplus(\neg x\land z)\\ \operatorname{Maj}(x,y,z)&=(x\land y)\oplus(x\land z)\oplus(y\land z) \end{aligned}

The uppercase Σ\Sigma functions used in rounds differ from the lowercase σ\sigma functions used in the schedule:

Σ0(x)=ROTR⁡2(x)⊕ROTR⁡13(x)⊕ROTR⁡22(x)Σ1(x)=ROTR⁡6(x)⊕ROTR⁡11(x)⊕ROTR⁡25(x)\begin{aligned} \Sigma_0(x)&=\operatorname{ROTR}_2(x)\oplus\operatorname{ROTR}_{13}(x)\oplus\operatorname{ROTR}_{22}(x)\\ \Sigma_1(x)&=\operatorname{ROTR}_6(x)\oplus\operatorname{ROTR}_{11}(x)\oplus\operatorname{ROTR}_{25}(x) \end{aligned}

The initial eight words are:

TEXT
6a09e667 bb67ae85 3c6ef372 a54ff53a
510e527f 9b05688c 1f83d9ab 5be0cd19

They come from the first 32 fractional bits of the square roots of the first eight primes. The 64 round constants come from cube roots of the first 64 primes; K0K_0 is 428a2f98. These values are fixed and public. Their origin makes them reproducible, not a proof of security. Curve Origins ⁠ examines that distinction for elliptic-curve parameters.

Add back and join

One step remains after round 63. Add each final working word to the corresponding word from before this block began, again keeping only 32 bits. This is called feed-forward.

For each of the eight positions:

output word=incoming word⊞final working word\text{output word}=\text{incoming word}\boxplus\text{final working word}
Input · abc · 61 62 63
Incoming H[0]6a09e667
+
Final a506e3058
=
H[0] · mod 2³²ba7816bf
SHA-256 digest8 × 4 B = 32 B

Select a word to see its addition and its place in the block output. On the last block, joining the eight results gives the final 32-byte digest. Earlier blocks produce an intermediate state instead.

For a longer message, those eight results become the starting state for the next block. Build that block's schedule, run 64 rounds, and add back again. Only after the last block do we serialize the state as the digest.

Why the mixing matters

A changed input bit enters both the schedule and the working state. Rotations move its influence across bit positions; Boolean selection and carries make the effect depend on the surrounding values. Repetition spreads that influence across the output. The avalanche effect emerges from this process.

This explains how the mixing happens, but it does not prove that reversing the hash is hard. A rotation, for example, is easy to undo. The difficult problem is finding an unknown message that satisfies the entire linked calculation when only the final digest is given. SHA-256's security depends on how well this specific construction withstands cryptanalysis.

For the full specification, see FIPS 180-4, sections 4–6.

This is 0xa.eth, building at OKX and exploring the mathematics behind cryptography, the mechanics of Ethereum, and the tools that shape how we think. I bring old computers back to life and experiment with AI, turning what I learn into visual notes and interactive experiments.