Zlib closes its stream with an Adler-32 checksum of the uncompressed data - a different algorithm from the chunk CRC32. Today you build Adler-32 so the decoder can verify the inflated bytes later.
Compute the Adler-32 checksum of a byte string as two running mod-65521 sums combined into one value.
Zlib ends every stream with a 4-byte Adler-32 of the original, uncompressed data - not to be confused with the CRC32 that guards each PNG chunk. Adler-32 is deliberately simpler and faster: keep two sums modulo the largest prime below 65536, which is 65521. Sum a starts at 1 and adds each byte; sum b starts at 0 and adds the running a after every byte, so it accumulates a position-weighted total. The final checksum packs them as b<<16 | a.
The starting value of 1 for a is why empty input checksums to 1, not 0 - a detail worth pinning so an off-by-one in the seed cannot hide. 0x11E60398 for Wikipedia is the textbook worked example for this algorithm. You will not need it until the encoder writes a zlib trailer and the decoder verifies one, but building it here keeps the whole zlib envelope in one chapter.
func Adler32(data []byte) uint32 {a, b := uint32(1), uint32(0)for _, c := range data {a = (a + uint32(c)) % 65521b = (b + a) % 65521}return b<<16 | a}