Difference between crc32() implementations of <linux/crc32.h> and <zlib.h> in C

Raunaq Kochar picture Raunaq Kochar · Nov 4, 2016 · Viewed 7.2k times · Source

I am calling two functions on my char* s = "pratik" as:

User code:

#include <zlib.h>
int main()
{
    char *s = "pratik";
    printf("%x\n",crc32(0x80000000, s, strlen(s)));
    return 0;
}

Output: 66fa3c99

Kernel code:

#include <linux/crc32.h>

int main()
{
    char *s = "pratik";

    u32 checksum = crc32(0x80000000, s, strlen(s));
    printk("\nChecksum --> %x", checksum);

    return checksum;
}

Output:

Checksum --> d7389d3a

Why are the values of the checksums on the same strings different?

Answer

Mark Adler picture Mark Adler · Nov 5, 2016

It appears that someone was disturbed by the fact that the standard Ethernet (PKZIP, ITU V.42 etc. etc.) CRC-32 does a pre- and post-exclusive-or with 0xffffffff. So the version in the Linux kernel leaves that out, and expects the application to do that. Go figure.

Anyway, you can get the same result as the (correct) zlib crc32(), using the (non-standard) Linux crc32() instead, thusly:

crc_final = crc32(crc_initial ^ 0xffffffff, buf, len) ^ 0xffffffff;

In fact, that exact same code would allow you to duplicate the Linux crc32() using the zlib crc32() as well.