Networking in C · intermediate · ~20 min

Checksums — integrity over the wire

Compute and verify CRC / Internet checksum on byte streams.

Overview

Checksums detect accidental corruption — single bit flips, dropped bytes — by mixing all input bytes into a fixed-size output. They are not security primitives; for adversarial integrity you need a MAC like HMAC.

Why it matters

Every wire protocol and binary format carries one. Reverse engineering a binary blob often starts with 'find the checksum'.

Core concepts

Internet checksum. One's complement sum of 16-bit words. Used in IP, TCP, UDP, ICMP. Cheap; detects many transmission errors.

CRC. Polynomial division in GF(2). CRC-8 (1-Wire), CRC-16 (XMODEM), CRC-32 (Ethernet, ZIP, PNG). Stronger than the Internet checksum but still not cryptographic.

Cryptographic hash. SHA-256, BLAKE3 — adversarial integrity. Use these (or HMAC) when an attacker may try to forge the input.

Pentester mindset. A checksum at the protocol layer doesn't stop tampering; an attacker who can write the data can recompute the checksum. Don't confuse the two.

Defensive coding habit. Use the right primitive: checksum for accidental corruption, MAC for adversarial integrity. Never invent your own.

Syntax notes

uint16_t inet_checksum(const uint8_t *buf, size_t len);  /* one's complement sum */
uint32_t crc32(const uint8_t *buf, size_t len);          /* poly 0xEDB88320 */

Lesson

A checksum compresses a buffer into a small integer such that any single byte change produces a different output. The Internet checksum (one's complement sum) is in every IP/TCP/UDP header; CRC-8/16/32 are in 1-Wire, Ethernet, ZIP, PNG, USB.

Code examples

unsigned char crc8(const unsigned char *d, size_t n){
    unsigned char c = 0;
    for (size_t i = 0; i < n; i++) {
        c ^= d[i];
        for (int b = 0; b < 8; b++)
            c = (c & 0x80) ? (c << 1) ^ 0x07 : c << 1;
    }
    return c;
}

Line by line

/* Internet checksum kernel */
uint32_t sum = 0;
for (size_t i = 0; i + 1 < len; i += 2)
    sum += (buf[i] << 8) | buf[i+1];
while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16);
return ~(uint16_t)sum;

Common mistakes

  • Reusing a checksum as a security MAC. Checksums detect accidental corruption, not adversarial tampering.

Debugging tips

The canonical CRC-8 test vector is '123456789' → 0xF4. Match against that.

Memory safety

Always cap the buffer length; never read past len. Sums use uint32_t to hold the carry.

Real-world uses

TCP/IP, Ethernet frames, ZIP/PNG/ELF files, USB packets, 1-Wire sensors.

Practice tasks

  1. Implement CRC-8 (poly 0x07). 2. Implement the Internet checksum. 3. Verify a known good IPv4 header.

Summary

Checksum for accidents, MAC for adversaries. Use the right primitive; never invent your own.

Practice with these exercises