13

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

Using zlib.h

#include <zlib.h>

int main()
{
    char *s = "pratik";
    printf("%x\n", crc32(0x80000000, s, strlen(s)));
    return 0;
}

Output: 66fa3c99

Using linux/crc32.h

#include <linux/crc32.h>

int main()
{
    char *s = "pratik";
    printf("%x\n", crc32(0x80000000, s, strlen(s)));
    return 0;
}

Output: d7389d3a

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

6
  • 2
    strlen(6)... are you sure? Commented Nov 4, 2016 at 6:59
  • 1
    Besides the possible errors in your code, keep in mind that CRC is actually a family of algorithms, parameterized by several options (first of all the digest size - always 32 bit in your case -, but also the polynomial used, the bits endianness, the initialization value, plus some extra bits manipulations that can be performed at various stages of the algorithm). Given that the kernel implementation is born to compute CRC values for network packets I wouldn't be surprised that it has reversed bit endianness. Some interesting info about CRC: ross.net/crc/download/crc_v3.txt. Commented Nov 4, 2016 at 7:14
  • 1
    While the generator polynomials appear to be the same (Linux references ITU V.42, which is identical to what zlib uses, there are little-endian and big-endian versions of crc32 in linux/crc32.h. Can you try calling crc32_be instead? Commented Nov 4, 2016 at 8:23
  • @mindriot When I run crc32_be(s), it prints B131FB25, which still doesn't match the user call and crc32_le(s) prints the same value as crc32(s) of the kernel program. Commented Nov 4, 2016 at 9:03
  • Maybe you also need to change the endianness of the seed value (replace 0x80000000 by 0x00000080 maybe)? To ensure that the seed is not causing the problem, I suggest you set it to 0 and compare the two crc32 versions again. Commented Nov 4, 2016 at 9:33

1 Answer 1

24

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.