1

I have the following problem: I'm trying to calculate the adler32 checksum of a data block using Crypto++, but I get the wrong checksum after converting the byte[4] array output to a uint32_t.

This function with crc32 works just fine:

CryptoPP::CRC32 crc;
byte digest[CryptoPP::CRC32::DIGESTSIZE];
crc.CalculateDigest(digest, (const byte*)pData.data(), pData.size());
uint32_t checksum = *(uint32_t*)digest; //this works fine

but the function calculating the adler32 returns a invalid value:

CryptoPP::Adler32 adler;
byte digest[CryptoPP::Adler32::DIGESTSIZE];
adler.CalculateDigest(digest, (const byte*)pData.data(), pData.size());
uint32_t checksum = *(uint32_t*)digest; //this returns a invalid value

hope someone could give me a hint.

greetz Fabian

coder
  • 10,460
  • 17
  • 72
  • 125
Fabian
  • 152
  • 2
  • 14

2 Answers2

0

The problem is that this code doesn't do what you want:

uint32_t checksum = *(uint32_t*)digest; //this returns a invalid value

This code says to read the digest as if it held a 32-bit integer in the form this CPU natively stores 32-bit integers. But it doesn't contain that. It contains an array of 4-bytes that represent the hash, but not as an x86-CPU style integer.

Try this:

uint32_t checksum = ntohl(*(uint32_t*)digest);

This says to read the raw bytes into an integer, and then convert them to X86 host format.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • i get the following compiler error: "undefined reference to `ntohl@4'" using mingw even tough i included winsock2.h. is there any other way to do this without a additional function? – Fabian Nov 17 '11 at 12:53
  • You can do something like this: `checksum=digest[0]; checksum<<=8; checksum|=digest[1]; checksum<<=8; checksum|=digest[2]; checksum<<=8; checksum|=digest[3];` – David Schwartz Nov 17 '11 at 16:45
  • It also a violation of the C/C++ standard. The punning uses a pointer aligned for bytes (which should be 1) versus an int (which should be 4). The value needs to be `memmov`'d or `memcpy`'d out. – jww Oct 02 '13 at 07:55
0

well i found out that crypto++'s adler32 implementation initializes s1 = 1; s2 = 0 in the adler32.h http://www.cryptopp.com/docs/ref/adler32_8h_source.html but it should be s1 = 0 and s2 = 0. now all my checksums are correct but i still dont get why cryto++'s implementation is "wrong". greetz Fabian

Fabian
  • 152
  • 2
  • 14
  • I believe that's because the checksum is calculated as `1 + d_1 + d_2 + ... + d_n`. If you omit the initialization to 1, you are not following the Adler32 algorithm. – jww Oct 02 '13 at 08:01