Table of Contents
- Introduction to Adler-32
- Why Adler-32 Uses Two Sums
- Limitation of Adler-32
- Worked Example: Adler-32 of "ABC"
- RFC Reference
- Conclusion
Introduction to Adler-32
Adler-32 is a 32-bit checksum algorithm designed by Mark Adler. It is primarily used by zlib and appears in many file formats and network protocols that rely on the DEFLATE compression format. Although simple and fast, Adler-32 is designed to detect accidental data corruption rather than malicious modifications.
Use case
Before understanding Adler-32, it's worth asking a simple question: why do we need checksums at all? When data is written to disk, transmitted over network, or copied between systems, individual bits may change because of hardware faults, electrical noise, storage failure or transmission errors. Even a single flipped bit can completely change the meaning of the data. A checksum provides a quick way to detect whether the received data is still identical to the original.
Transmission flow
Original Data
|
Compute Adler-32
|
+--------------------------+
| Data | Adler-32 |
+--------------------------+
|
Transmission
|
Receiver
|
Recompute Adler-32
|
Compare
Compare Match? -> Data accepted
Compare Different? -> Data corruptedCorruption scenarios
Three outcomes are possible.
- The data is corrupted while the checksum is transmitted correctly. The receiver computes a different checksum and detects the error.
- The checksum itself is corrupted. The recomputed checksum no longer matches the transmitted checksum, so the receiver again detects an error.
- Both the data and the checksum are corrupted. In most cases the mismatch is still detected. However, there is a small probability that the corrupted data produces exactly the corrupted checksum. This situation is known as a collision. Good checksum algorithms are designed so that such collisions are unlikely to occur accidentally.
Implementation
To understand Adler-32 in practice, we can implement a small version of the algorithm in C. The implementation follows the definition of Adler-32: maintaining two running sums, A and B, and combining them into a single 32-bit checksum at the end.
The complete implementation does not require any external libraries.
Constants
#define BASE_MODULO 65521
#define INIT_SUM_A 1
#define INIT_SUM_B 0Adler-32 uses two 16-bit sums internally:
- A starts with the value 1
- B starts with the value 0
The calculations are performed modulo 65521, which is the largest prime number smaller than 2^16. The modulo operation keeps both sums within a predictable range while allowing the final result to fit into a 32-bit value.
Maintaining the Two Sums
The core of Adler-32 is the update of the two accumulators:
uint32_t sumA = INIT_SUM_A;
uint32_t sumB = INIT_SUM_B;
for (size_t i = 0; i < message_size; i++) {
sumA += message[i];
sumB += sumA;
sumA %= BASE_MODULO;
sumB %= BASE_MODULO;
}For every byte in the input:
- Add the byte value to sumA.
- Add the new value of sumA to sumB.
- Reduce both values using modulo 65521.
The first sum represents the accumulated value of all bytes:
A = 1 + byte1 + byte2 + ... + byten
The second sum represents the accumulation of all previous values of A:
B = A1 + A2 + A3 + ... + An
Because B depends on the history of A, it can detect changes in both the value and the position of bytes.
Combining the Final Checksum
After processing all bytes, Adler-32 combines both 16-bit sums into a single 32-bit value:
return (sumB << 16) + sumA;The final checksum layout is:
31 16 15 0
+------------------+------------------+
| B | A |
+------------------+------------------+The upper 16 bits contain B, and the lower 16 bits contain A. For example:
A = 0x1234
B = 0xabcd
Result: 0xabcd1234Why Adler-32 Uses Two Sums
The first sum, A, tracks the total of all bytes in the message. If only A were used, different byte sequences could produce the same result.
The second sum, B, tracks the running history of A. This makes the checksum sensitive to the position of each byte as well as its value.
A starts at 1 instead of 0 so that an empty message produces a non-zero checksum (0x00000001), which avoids a special all-zero result.
Limitation of Adler-32
Adler-32 is extremely fast and simple, but it has weaker error-detection properties than stronger checksums such as CRC32.
In particular:
- It produces more collisions than CRC32.
- Its distribution is weaker for very short messages.
- It is not resistant to intentional modification.
For this reason, Adler-32 is best suited for detecting accidental corruption in compressed data streams, while cryptographic hashes such as SHA-256 should be used when security is required.
Worked Example: Adler-32 of "ABC"
To see how Adler-32 works, let's calculate the checksum for the string "ABC".
ASCII values:
A = 65
B = 66
C = 67Initial values:
sumA = 1
sumB = 0After processing 'A' (65):
sumA = 1 + 65 = 66
sumB = 0 + 66 = 66After processing 'B' (66):
sumA = 66 + 66 = 132
sumB = 66 + 132 = 198After processing 'C' (67):
sumA = 132 + 67 = 199
sumB = 198 + 199 = 397The final Adler-32 checksum is:
sumA = 199 = 0x00C7
sumB = 397 = 0x018D
checksum = (sumB << 16) | sumA
= 0x018D00C7Therefore, the Adler-32 checksum of "ABC" is:
0x018D00C7Notice that sumA tracks the cumulative byte values, while sumB accumulates the history of sumA. This is what makes Adler-32 sensitive to both the values and the order of the bytes. (Here the sums are combined with a bitwise OR instead of addition, as in the earlier C code, both give the same result, since sumA never exceeds 16 bits and so the two halves never overlap.)
RFC Reference
Adler-32 was first formally specified in RFC 1950, which defines the zlib compressed data format. Section 2.2 of that document describes the algorithm precisely, including the initial values A=1 and B=0, the modulo 65521 operation, and the final combination of the two 16‑bit sums into a 32‑bit checksum. You can read the full specification at RFC 1950 – ZLIB Compressed Data Format Specification.
Because Adler-32 is part of the zlib format, it appears anywhere zlib streams are used, most notably inside PNG image files, whose compressed pixel data is wrapped in a zlib stream, and in protocols that use zlib-style "deflate" content encoding. It's worth noting that gzip files and ZIP archives, although they also rely on DEFLATE compression (defined separately in RFC 1951), do not use Adler-32 for their checksums, they use CRC-32 instead. The full DEFLATE specification is available at RFC 1951 – DEFLATE Compressed Data Format Specification.
Conclusion
Adler-32 remains a practical checksum choice when speed and simplicity outweigh the need for cryptographic security. As we saw in the Why Adler-32 Uses Two Sums section, the two‑accumulator design makes the checksum sensitive to both byte values and their positions, catching common transmission errors with very little computational overhead.
However, the Limitation of Adler-32 discussion makes clear that it is not suitable for all situations. Short messages and highly repetitive data can lead to a higher collision rate than a CRC‑32, and the algorithm offers no protection against intentional tampering.
When selecting a checksum, consider the nature of your data and the threats you face:
- For accidental corruption in bulk data streams, Adler-32 is an excellent, lightweight option.
- When you need stronger error detection but still want performance, CRC‑32 is often a better fit.
- If data integrity is critical, whether against accidental changes or deliberate modification, use a cryptographic hash like SHA‑256 instead.
Ultimately, Adler-32 has earned its place in the history of data integrity by being small, fast, and good enough for its intended purpose. Understanding how it works, as detailed in this guide, helps you decide exactly when "good enough" is the right engineering choice.