A long message is many blocks, and each one is compressed in turn with the hash state carried forward from the last. Today you build that loop and pin the state after a two-block message - the Merkle-Damgard chaining that makes SHA-256 work on any length.
Compress a sequence of blocks, threading the hash state from each block into the next.
A message longer than 55 bytes spans several blocks, and SHA-256 handles them by chaining: start from the initial hash values, compress the first block to get an intermediate state, feed that as the input hash to the second block, and so on
Pin it with the classic two-block vector, the 56-byte message that (from lesson 11)
padded into exactly two blocks. Compress both in sequence and the final state is
0x248d6a61 0xd20638b8 0xe5c02693 0x0c3e6039 0xa33ce459 0x64ff2167 0xf6ecedd4 0x19db06c1. If block 2 were fed the initial hash instead of block 1’s output - a
common chaining bug - this would come out wrong, so matching it proves the state
really threads through. All that is left is to wire padding and blocking in front
of this loop and serialize the eight words into a digest.
func CompressBlocks(blocks [][]byte) [8]uint32 {h := InitialHash()for _, block := range blocks {h = Compress(h, block) // each block updates the running state}return h}