SHA-256 processes fixed 512-bit blocks, so any message must first be padded to a whole number of blocks. Today you build the padding rule - a 1 bit, then zeros, then the length - and pin the exact bytes for the message "abc".
Pad a byte message with 0x80, zero bytes, and a 64-bit length so its total length is a multiple of 64 bytes.
SHA-256 only ever consumes complete 512-bit (64-byte) blocks, so before
hashing, the message is padded to a whole number of them. The rule has three
parts, always in this order: append a single 1 bit (a whole 0x80 byte, since
messages here are whole bytes), then as many 0 bits as needed, then the original
message length as a 64-bit big-endian integer counting bits. The zeros are
chosen so that everything lands exactly on a 64-byte boundary.
For "abc" that means 0x61 0x62 0x63, then the 0x80 marker, then zeros out to
byte 56, then the 8-byte length. The length is the crucial subtlety: it is the
message size in bits, not bytes, so 3 bytes becomes 24, which is 0x18,
right-aligned in the 64-bit field as 00 00 00 00 00 00 00 18. That fills the
block to exactly 64 bytes. Appending the length lets the hash tell messages apart
that would otherwise pad identically, and encoding it in bits (not bytes) is a
detail the standard is strict about - get it wrong and every digest is wrong.
func Pad(msg []byte) []byte {out := append([]byte{}, msg...)out = append(out, 0x80) // the single 1 bit, as a whole bytefor len(out)%64 != 56 { out = append(out, 0x00) }// append uint64(len(msg)*8) as 8 big-endian bytes// (fill in)return out}