How-To use CRC32 checksums
You want to detect whether data has been corrupted? Good old CRC32 to the rescue!
Basics
CRC32 calculates a 32 bit checksum over data; if a bit gets flipped in the data, you get a different checksum. Of course, this is not cryptographically secure, and collisions do occur – but it’s rare enough that as a checksum, CRC32 remains useful.
We define two types:
liberate::checksum::crc32_checksum
is platform dependent in size, but at least 32 bits long. It’s an alias forstd::uint_fast_32t
and should be used for calculating sums.liberate::checksum::crc32_serialize
on the other hand is a 32-bit type that you can assign your calculated value to, and serialize it as only four bytes.
1#include <liberate/liberate/checksum.h>
2
3using namespace liberate::checksum;
4
5char buf1[] = { /* something */ };
6std::vector<char> buf2; // Initialize with something
7
8auto sum1 = crc32(buf1, buf1 + sizeof(buf1));
9auto sum2 = crc32(buf2.begin(), buf2.end());
You just apply the liberate::checksum::crc32()
function to some
range, and it calculates the sum. The only constraint is that the range’s
value type is some 8 bit integer type.
Note
As an implementation detail, the entire CRC32 lookup table is calculated
at compile time as a constexpr
value, meaning calculation of CRC32
checksums should yield about as compact code as you can get without dipping
into assembly.
No, there are no benchmarks. But if you run tests, let us know!
Polynomials
So now you have a CRC32 checksum. Ahh, but which CRC32?
Well, you can choose. CRC32 describes both an algorithm, and a polynomial to use in the algorithm, but people have used different polynomials for different purposes.
This library defaults to the “normal” polynomial, as defined by ISO3309 and the
IEEE 802.3 standards, and POSIX, etc. But there are a few more as you can see
in liberate::checksum::crc32_polynomials
. You just add the enum
value as a third parameter:
1auto sum1 = crc32(buf1, buf1 + sizeof(buf1));
2auto sum2 = crc32(buf2.begin(), buf2.end(), CRC32_CASTAGNOLI);
3assert(sum1 != sum2);
Serialization
Serialize CRC32 in 32 bits:
1crc32_serialize tmp = sum1;
2auto used = liberate::serialization::serialize_int(out, sizeof(out), tmp);
See also