A checksum is an error detection method widely used in computer networks. It allows the sender to generate a small fixed-size value from a message, which the receiver then uses to verify whether the data arrived intact. If even a single bit changes during transmission, the checksum will detect the discrepancy.
Checksums operate at the higher layers of the network protocol stack (such as TCP, UDP, and IP) and involve two components:
- Checksum Generator (sender side): Computes a checksum from the original message and appends it to the data before sending.
- Checksum Checker (receiver side): Recomputes the checksum from the received data and verifies it against the transmitted checksum.
In this guide, you will learn how the checksum algorithm works step by step and how to implement both the sender and receiver sides in Python.
How the Checksum Algorithm Works
Sender Side: Generating the Checksum
- Divide the message into fixed-size segments of k bits each.
- Add all segments together using binary addition.
- If the sum has more than k bits, wrap around by adding the overflow bits back to the remaining k bits.
- Complement the final sum (flip all bits:
1→0,0→1). This is the checksum. - Send the original message along with the checksum.
Receiver Side: Verifying the Checksum
- Divide the received message into the same k-bit segments.
- Add all segments together with the received checksum.
- Handle any overflow by wrapping around, just like on the sender side.
- Complement the result.
- If the final value is all zeros, the data is accepted (no error detected). Otherwise, an error is detected and the data is rejected.
Implementing the Checksum Generator
The sender divides the message into segments, sums them, handles overflow, and complements the result:
def find_checksum(message, k):
"""
Compute the checksum for a binary message string.
Args:
message: A binary string (e.g., '10010101011000111001010011101100')
k: The segment size in bits (e.g., 8)
Returns:
The checksum as a binary string of length k.
"""
segments = [message[i:i + k] for i in range(0, len(message), k)]
total = sum(int(seg, 2) for seg in segments)
binary_sum = bin(total)[2:] # Remove '0b' prefix
while len(binary_sum) > k:
overflow = len(binary_sum) - k
binary_sum = bin(int(binary_sum[:overflow], 2) + int(binary_sum[overflow:], 2))[2:]
binary_sum = binary_sum.zfill(k)
checksum = ''.join('0' if bit == '1' else '1' for bit in binary_sum)
return checksumKey details:
bin(total)[2:]converts an integer to its binary string representation and strips the'0b'prefix.- The
whileloop handles cases where the sum overflows beyond k bits by repeatedly folding the overflow back in. .zfill(k)ensures the result is zero-padded to exactly k bits.
Implementing the Checksum Checker
The receiver performs the same segmentation and addition, but also includes the received checksum in the sum:
def verify_checksum(received_message, k, checksum):
"""
Verify the integrity of a received message using its checksum.
Args:
received_message: The binary message string received.
k: The segment size in bits.
checksum: The checksum received from the sender.
Returns:
The complement of the receiver's sum. All zeros means no error.
"""
segments = [received_message[i:i + k] for i in range(0, len(received_message), k)]
total = sum(int(seg, 2) for seg in segments) + int(checksum, 2)
binary_sum = bin(total)[2:]
while len(binary_sum) > k:
overflow = len(binary_sum) - k
binary_sum = bin(int(binary_sum[:overflow], 2) + int(binary_sum[overflow:], 2))[2:]
binary_sum = binary_sum.zfill(k)
result = ''.join('0' if bit == '1' else '1' for bit in binary_sum)
return resultIf the returned string is all zeros ('00000000' for k=8), the data passed the integrity check.
Complete Implementation with Error Detection
Here is the full program combining both sender and receiver logic, along with the final acceptance/rejection decision:
def find_checksum(message, k):
"""Compute the checksum for a binary message."""
segments = [message[i:i + k] for i in range(0, len(message), k)]
total = sum(int(seg, 2) for seg in segments)
binary_sum = bin(total)[2:]
while len(binary_sum) > k:
overflow = len(binary_sum) - k
binary_sum = bin(int(binary_sum[:overflow], 2) + int(binary_sum[overflow:], 2))[2:]
binary_sum = binary_sum.zfill(k)
checksum = ''.join('0' if bit == '1' else '1' for bit in binary_sum)
return checksum
def verify_checksum(received_message, k, checksum):
"""Verify the received message against the checksum."""
segments = [received_message[i:i + k] for i in range(0, len(received_message), k)]
total = sum(int(seg, 2) for seg in segments) + int(checksum, 2)
binary_sum = bin(total)[2:]
while len(binary_sum) > k:
overflow = len(binary_sum) - k
binary_sum = bin(int(binary_sum[:overflow], 2) + int(binary_sum[overflow:], 2))[2:]
binary_sum = binary_sum.zfill(k)
result = ''.join('0' if bit == '1' else '1' for bit in binary_sum)
return result
if __name__ == "__main__":
sent_message = "10010101011000111001010011101100"
k = 8
checksum = find_checksum(sent_message, k)
print(f"Sender Checksum: {checksum}")
received_message = "10010101011000111001010011101100"
receiver_result = verify_checksum(received_message, k, checksum)
print(f"Receiver Verification Result: {receiver_result}")
if int(receiver_result, 2) == 0:
print("STATUS: ACCEPTED- No error detected.\n")
else:
print("STATUS: REJECTED- Error detected!\n")
corrupted_message = "10000101011000111001010011101101" # Bits changed
corrupted_result = verify_checksum(corrupted_message, k, checksum)
print(f"Corrupted Message Verification Result: {corrupted_result}")
if int(corrupted_result, 2) == 0:
print("STATUS: ACCEPTED- No error detected.")
else:
print("STATUS: REJECTED- Error detected!")Output:
Sender Checksum: 10000101
Receiver Verification Result: 00000000
STATUS: ACCEPTED- No error detected.
Corrupted Message Verification Result: 00001111
STATUS: REJECTED- Error detected!Step-by-Step Walkthrough
Let's trace through the algorithm with the example message 10010101011000111001010011101100 and segment size k = 8:
Sender side:
| Step | Operation | Result |
|---|---|---|
| 1 | Divide into 8-bit segments | 10010101, 01100011, 10010100, 11101100 |
| 2 | Convert and sum | 149 + 99 + 148 + 236 = 632 |
| 3 | Binary sum | 1001111000 (10 bits- overflows 8) |
| 4 | Wrap overflow: 10 + 01111000 |
01111010 (8 bits) |
| 5 | Complement | 10000101 ← Checksum |
Receiver side (no errors):
| Step | Operation | Result |
|---|---|---|
| 1 | Sum all segments + checksum | 149 + 99 + 148 + 236 + 133 = 765 |
| 2 | Binary sum | 1011111101 (10 bits) |
| 3 | Wrap overflow: 10 + 11111101 |
11111111 |
| 4 | Complement | 00000000 ← All zeros = ACCEPTED |
Making the Implementation More Flexible
The examples above assume the message length is exactly divisible by k and contains exactly 4 segments. Here's a more robust version that handles any message length:
def find_checksum_flexible(message, k):
"""Handle messages of any length, padding the last segment if needed."""
remainder = len(message) % k
if remainder != 0:
message = message.zfill(len(message) + (k - remainder))
segments = [message[i:i + k] for i in range(0, len(message), k)]
total = sum(int(seg, 2) for seg in segments)
binary_sum = bin(total)[2:]
while len(binary_sum) > k:
overflow = len(binary_sum) - k
binary_sum = bin(int(binary_sum[:overflow], 2) + int(binary_sum[overflow:], 2))[2:]
binary_sum = binary_sum.zfill(k)
checksum = ''.join('0' if bit == '1' else '1' for bit in binary_sum)
return checksumComplexity Analysis
| Aspect | Value |
|---|---|
| Time Complexity | O(n), where n is the length of the message. Each bit is processed once during segmentation and summation. |
| Space Complexity | O(n/k) for storing the segments, plus O(k) for the checksum string. |
Conclusion
The checksum algorithm provides a straightforward and efficient way to detect transmission errors in computer networks. By dividing a message into fixed-size segments, summing them, and complementing the result, both sender and receiver can verify data integrity with minimal computational overhead.
While checksums cannot detect all possible error patterns, they are fast, easy to implement, and form the foundation of error detection in protocols like TCP, UDP, and IP. For applications requiring stronger error detection, consider using CRC or cryptographic hash functions like SHA-256.