SHA-256, step by step — and what each step is for
A complete SHA-256 in plain client-side JavaScript. Step through padding, the message schedule, all 64 compression rounds and the feed-forward — with the plain-English reason each step exists, the pitfalls that catch students, and a question to check yourself. Every number is computed live on this page, and the final digest is compared against your browser's own SHA-256.
Avalanche: flip input bits, watch the output scramble
The security of a hash rests on diffusion: change one input bit and roughly half of the 256 output bits should change, with no visible pattern. Both digests are computed live by the implementation on this page.
Notation
| ⊤ — a word | A 32-bit value, written in hex. All arithmetic on words is modulo 232 unless said otherwise. |
| a b c d e f g h | The eight working registers, one word each. Together they are the 256-bit state. |
| W[t] | Message schedule word for round t. W[0..15] come from the block, W[16..63] are expanded. |
| K[t] | Round constant for round t — 64 of them, fixed by the standard. |
| H1..8 | The chaining value. Starts at H⁽⁰⁾, updated once per block; at the end it is the digest. |
| rotr(x,n) | Rotate right by n bits: bits falling off the right end reappear at the left. A rotation loses nothing. |
| x >> n | Shift right by n bits: bits falling off are discarded and zeros enter at the top. A shift loses information. |
| σ₀ σ₁ (lowercase) | Linear functions of the message schedule: σ₀(x)=rotr(x,7)⊕rotr(x,18)⊕(x>>3) and σ₁(x)=rotr(x,17)⊕rotr(x,19)⊕(x>>10). |
| Σ₀ Σ₁ (uppercase) | Linear functions of the state applied in every round: Σ₀(a)=rotr(a,2)⊕rotr(a,13)⊕rotr(a,22) and Σ₁(e)=rotr(e,6)⊕rotr(e,11)⊕rotr(e,25). |
| Ch(e,f,g) | Bitwise choose: output bit = f's bit where e=1, else g's bit. Nonlinear. |
| Maj(a,b,c) | Bitwise majority of the three bits. Nonlinear. |
| T1, T2 | The two temporary sums computed each round before the registers shift. |
| ⊕ | Bitwise XOR — addition without carries, i.e. addition in GF(2) bit by bit. |
Glossary
Block, word, and why 512 and 32
A word is 32 bits — the natural integer size of the design, giving arithmetic modulo 2³². A block is 512 bits = 16 words = 64 bytes, the amount the compression function consumes in one go. SHA-512 is the same design with 64-bit words, 1024-bit blocks and 80 rounds: the word size, round count and constants change, the structure does not.
Merkle–Damgård construction
To hash arbitrary-length input with a fixed-size compression function f, pad to a multiple of the block size and iterate: Hi = f(Hi−1, Mi). Collision resistance of the whole function reduces to collision resistance of f, provided the padding encodes the message injectively. The construction is however not indifferentiable from a random oracle — exactly the weakness behind length extension.
Length extension attack (and HMAC)
Because the digest is the final chaining value, an attacker given h(M) and the length |M| can compute
h(M ‖ pad(M) ‖ X) for any suffix X they choose, without knowing M: set the state to h(M) and keep compressing. This breaks the
naive MAC SHA-256(secret ‖ message). HMAC fixes it by hashing the key twice —
SHA-256(K⊕opad ‖ SHA-256(K⊕ipad ‖ M)) — which keeps the internal state out of the attacker's hands.
ARX design: no S-boxes
SHA-256 mixes with only three primitives: Addition mod 2³², Rotation, eXclusive-or. AES takes its nonlinearity from substitution tables; SHA-256 takes it from Ch, Maj and the carry chains inside the modular additions. ARX is cheap in hardware and easy to implement in constant time.
Diffusion, avalanche, and where 64 rounds comes from
Diffusion means every output bit depends on every input bit. Avalanche is the statistical version: flipping one input bit flips each output bit with probability ≈ ½. Both build up over rounds — one round barely mixes, 64 rounds leave total dependence. The round count is a safety margin informed by cryptanalysis, not a provable bound: the best published collisions target step-reduced variants well below 64 rounds.
What hashing is and is not
SHA-256 is keyless and one-way: it provides integrity (did these bytes change?) but not confidentiality, and a digest is not a ciphertext — there is nothing to decrypt, the mapping is many-to-one with no inverse. Its three standard goals: preimage resistance (~2²⁵⁶), second-preimage resistance (~2²⁵⁶) and collision resistance (~2¹²⁸ by the birthday bound). It is also the wrong tool for passwords: it is deliberately fast. Password storage needs a slow salted KDF — Argon2, scrypt or bcrypt.
Friends and neighbours
MD5 (1991) and SHA-1 (1995) are broken — practical collisions exist for both (SHA-1: SHAttered, 2017), so neither is safe for signatures or certificates. SHA-2 (2001) — SHA-256, SHA-512 and the truncated SHA-512/256 — remains unbroken. SHA-3 (2015) is a different, sponge-based design (Keccak), standardised so that a future break of SHA-2 would not take the whole ecosystem with it.
Where the constants come from — "nothing up my sleeve"
H⁽⁰⁾ derives from the square roots of the first eight primes; K[t] from the cube roots of the first sixty-four. Take the fractional part, multiply by 232, round down. The tables below are recomputed live in your browser and compared with the constants the algorithm actually uses.