English

Developer tools · SHA hash calculator

SHA-256 Step by Step: Padding, Message Schedule and 64 Rounds

· How it works

sha-256 cryptography browser-apis javascript

Diagram showing message padding, block division, 64-round processing loop and final hash combination
Original ToolAcre vector illustration

SHA-256 pads your input, splits it into 512-bit blocks and runs each through 64 rounds of mixing. This post explains every stage in plain language without requiring a cryptography background.

What actually happens to your bytes — the black box most developers never open

SHA-256 is a deterministic algorithm that transforms any input into a 256-bit (32-byte) fingerprint. What looks like a black box from the outside is actually a sequence of well-defined steps. Understanding those steps removes the mystery and lets you verify correctness, trace bugs and understand why the output is what it is. Every piece of the algorithm is public; the strength comes from the design, not from secrecy.

The algorithm operates on 512-bit blocks. If your input is shorter, it gets padded. If it is longer, it gets split into multiple blocks, each processed in sequence, with each block's output feeding into the next. After all blocks are processed, you have eight 32-bit numbers that, concatenated together, form the final 256-bit digest.

Padding — appending a 1 bit, zeros and the 64-bit message length to reach a multiple of 512 bits

The padding step is deterministic and formalized. After your actual input, append a single 1 bit (in practice, the byte 0x80 if your input ends on a byte boundary). Then append zero bits until you are 64 bits short of a multiple of 512 bits. Finally, append a 64-bit big-endian encoding of the input length in bits. This padding ensures every message is a multiple of 512 bits and encodes the original length so identical inputs of different lengths cannot produce the same digest.

For the input abc (3 bytes = 24 bits), the padded message is 512 bits (one block): the three bytes 61 62 63, followed by 0x80, followed by zeros, followed by the 64-bit encoding of 24 (which is 0x00...0x18 in a 64-bit big-endian field). The message now fills exactly one 512-bit block. For an empty string, the padding appends 0x80, followed by zeros, followed by 0x00...0x00 (indicating 0 bits of input). For a longer input like a 100-byte file, the padding would fill the last block to 512 bits and indicate 800 bits of original length.

The initial values and constants are fixed by the algorithm; their historical derivation is outside repository evidence

The algorithm starts with eight 32-bit working variables, initialized to the first 32 bits of the fractional parts of the square roots of the first eight prime numbers. These are hard-coded constants, visible in any reference implementation and in the source code of cryptographic libraries. They exist because using fixed constants from mathematics avoids suspicion of a hidden backdoor. The ToolAcre tool uses the browser's Web Crypto implementation, which applies these same constants.

The algorithm also uses 64 round constants, derived from the first 32 bits of the fractional parts of the cube roots of the first 64 prime numbers. These are also fixed and public. The constants serve as additional mixing material; changing them would break the algorithm and produce different digests.

The message schedule — expanding 16 words into 64 with shifts and rotations

The message schedule expands 16 words (512 bits) into 64 words (2048 bits) via a specific formula. For rounds 0-15, the words come directly from the input block. For rounds 16-63, each new word is computed by taking two earlier words (at specific offsets), applying a rotation and shift, XORing in another word, and storing the result. The formula is deterministic and reversible within the context of one block, but the expansion spreads the influence of the input across all 64 rounds.

The expansion formula uses rotate-right (a circular bit shift where bits that fall off one end reappear at the other) and right-shift operations. Rotation preserves all bits but changes their positions; right-shift discards bits. The combination of rotations, shifts and XOR operations ensures that every bit of the input influences multiple words in the schedule.

One round — the Ch, Maj and Sigma functions described as bit-mixing operations, and how eight working variables update

Each of the 64 rounds processes one word of the message schedule and updates the eight working variables. The core function involves six operations: a conditional mix (often called Ch, for "choose") that selects bits based on a control variable, a majority function (Maj) that picks the most common value among three variables, two special mixing functions (Sigma_0 and Sigma_1) that rotate and shift the working variables, and addition modulo 2^32. All arithmetic is done on 32-bit words, so overflow wraps around.

The "choose" function takes three 32-bit inputs and, for each bit position, selects the bit from the first input if a control bit is 1, or the bit from the second input if the control bit is 0. The majority function looks at three inputs and, for each bit position, outputs the bit value that appears most often among the three. These are non-linear operations that break linearity and ensure that tiny input changes propagate unpredictably through the state.

Chaining blocks and producing the output — adding each block's result into the running state

Each round updates all eight working variables by rotating them and incorporating a new value computed from the current round constant, the message schedule word, and the previous state. The first seven working variables shift: the 8th becomes the 1st, the 1st becomes the 2nd, and so on. The new 8th is computed from the old variables using the mixing functions. After 64 rounds, you have eight new 32-bit values. These are added (modulo 2^32) to the initial constants, producing the final hash state for this block.

For a multi-block message, the eight values from one block become the initial state for the next block. The chain ensures that a change anywhere in the input affects all subsequent blocks. By the time you reach the final block, every bit of the input has influenced the final output.

Worked example and what this does not cover — tracing the padding and block count for a short message; security proofs are out of scope

For the input abc, the message fits in one 512-bit block after padding. The padding adds 424 bits, making the total 512 bits. The message schedule expands this to 64 words. Each round consumes one word and updates the eight working variables through the mixing functions. After 64 rounds, the state is XORed with the initial constants, producing the final digest ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad.

This is a published test vector: the same computation on the same input always produces the same output. The ToolAcre tool performs this exact computation via the browser's Web Crypto implementation. You can verify it by hashing abc and comparing the result to the known vector. Any browser that implements Web Crypto correctly will produce the same output; the algorithm admits no shortcuts or alternative paths.

Takeaway: Web Crypto performs deterministic SHA-256 mixing without exposing a secret

The algorithm is public, and every step is deterministic. The mixing functions (Ch, Maj, Sigma_0, Sigma_1) were chosen to be non-linear, meaning that changing one input bit does not predictably change one output bit. The expansion of 16 message words to 64 ensures that the entire input influences the entire computation. The 64 rounds and the chaining of state mean that the output is sensitive to every bit of the input, and the repository uses the resulting output as a deterministic digest. Collision resistance is a security property with limits, not a promise that duplicate outputs are mathematically impossible.

Cryptographic proofs are beyond the scope of this post. The key point is that you now know what the algorithm actually does. It is not magic, and it is not a black box. If you want to verify that ToolAcre is hashing correctly, trace your own input through these steps, or use a reference implementation in another language and compare results. The browser's implementation and any correct reference will produce identical digests for identical inputs.