Search code examples
c#adler32

Adler-32 checksum generating - why bit and shift right operator are used


I've found method which implements Adler32 algorithm in C# and I would like to use it, but I do not understand part of the code:

Can someone explain me:

1) why bit operators are used when sum1, and sum2 are initialized

2) why sum2 is shifted ?

Adler32 on wiki https://en.wikipedia.org/wiki/Adler-32

& operator explanation: (Binary AND Operator copies a bit to the result if it exists in both operands)

private bool MakeForBuffer(byte[] bytesBuff, uint adlerCheckSum)
    {
        if (Object.Equals(bytesBuff, null))
        {
            checksumValue = 0;
            return false;
        }
        int nSize = bytesBuff.GetLength(0);
        if (nSize == 0)
        {
            checksumValue = 0;
            return false;
        }
        uint sum1 = adlerCheckSum & 0xFFFF; // 1) why bit operator is used?
        uint sum2 = (adlerCheckSum >> 16) & 0xFFFF; // 2) why bit operator is used? , why is it shifted?

        for (int i = 0; i < nSize; i++)
        {
            sum1 = (sum1 + bytesBuff[i]) % adlerBase;
            sum2 = (sum1 + sum2) % adlerBase;
        }
        checksumValue = (sum2 << 16) + sum1;
        return true;
    }

Solution

  • 1) why bit operator is used?

    & 0xFFFF sets the two high bytes of the checksum to 0, so sum1 is simply the lower 16 bits of the checksum.

    2) why bit operator is used? , why is it shifted?

    adlerCheckSum >> 16 shifts the 16 higher bytes down to the lower 16 bytes, & 0xFFFF does the same as in the first step - it sets the 16 high bits to 0.

    Example

    adlerChecksum = 0x12345678
    
    adlerChecksum & 0xFFFF = 0x00005678
    
    adlerChecksum >> 16 = 0x????1234
    

    (it should be 0x00001234 in C# but other languages / compilers "wrap the bits around" and you would get 0x56781234)

    (adlerChecksum >> 16) & 0xFFFF = 0x00001234 now you can be sure it's 0x1234, this step is just a precaution that's probably unnecessary in C#.

    adlerChecksum = 0x12345678
    sum1 =          0x00005678
    sum2 =          0x00001234
    

    Those two operations combined simply split the UInt32 checksum into two UInt16.


    From the adler32 Tag-Wiki:

    Adler-32 is a fast checksum algorithm used in zlib to verify the results of decompression. It is composed of two sums modulo 65521. Start with s1 = 1 and s2 = 0, then for each byte x, s1 = s1 + x, s2 = s2 + s1. The two sums are combined into a 32-bit value with s1 in the low 16 bits and s2 in the high 16 bits.