Arnaud F.
Arnaud F.

Reputation: 8452

Equivalent to Unix cksum in Windows

I download a file and his checksum (generated by cksum Unix command).

So, I want, in my C# app test if the Checksum is in adequation with the app I downloaded.

I checked at the Unix man page of chsum:

  The cksum command calculates and prints to standard output a checksum
  for each named file, the number of octets in the file and the
  filename.

  cksum uses a portable algorithm based on a 32-bit Cyclic Redundancy
  Check.  This algorithm finds a broader spectrum of errors than the
  16-bit algorithms used by sum (see sum(1)).  The CRC is the sum of the
  following expressions, where x is each byte of the file.

       x^32 + x^26 + x^23 +x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7
       + x^5 + x^4 + x^2 + x^1 + x^0

  The results of the calculation are truncated to a 32-bit value.  The
  number of bytes in the file is also printed.

So i wrote a simple program that does the sum :

byte[] arr = File.ReadAllBytes(@"MyApp").ToArray();

int cksum = 0;

foreach (byte x in arr)
{
    cksum += (x ^ 32 + x ^ 26 + x ^ 23 + x ^ 22 + x ^ 16 + x ^ 12 + x ^ 11 + x ^ 10 + x ^ 8 + x ^ 7 + x ^ 5 + x ^ 4 + x ^ 2 + x ^ 1 + x ^ 0);
}

But checksums aren't the same, how can I fix this?

Thanks


EDIT

1) The modified algorithm is:

uint cksum = 0;

foreach (byte b in arr)
{
    var x = (uint)b;

    cksum += (IntPow(x, 32)
        + IntPow(x, 26) + IntPow(x, 23) + IntPow(x, 22)
        + IntPow(x, 16) + IntPow(x, 12) + IntPow(x, 11) + IntPow(x, 10)
        + IntPow(x, 8) + IntPow(x, 7) + IntPow(x, 5) + IntPow(x, 4) + IntPow(x, 2) + IntPow(x, 1) + IntPow(x, 0));
}

2) I used the class Crc32 : HashAlgorithm

Given an Unix file where the Crc32 is : 2774111254

What I'm doing wrong !?

Upvotes: 2

Views: 3517

Answers (4)

Carlos Rendon
Carlos Rendon

Reputation: 6232

Also see this correct implementation https://cksum.codeplex.com/

Upvotes: 2

Mutation Person
Mutation Person

Reputation: 30520

In C# the ^ symbol is the exclusive-or operator. You want the function Math.Pow.

This gives the piower of two floating point numbers, alteratives are suggested at How do you do *integer* exponentiation in C#?

So, your code would look something like:

cksum += Math.pow(x,32) + Math.pow(x,26)

Be aware also of the last statement:

The results of the calculation are truncated to a 32-bit value. The number of bytes in the file is also printed.

Is this signed (int) or unsigned (uint)

you could of course use the following: http://www.codeproject.com/Articles/35134/How-to-calculate-CRC-in-C

Upvotes: 2

Jack V.
Jack V.

Reputation: 1381

In c# ^ is not a raise-to-the-power operator, but an xor operator, whereas the CRC is written using general mathsy terminology not specific to any language.

Don't use a standard "pow" function either since those will normally use floating point to represent very large numbers such as x^32.

Whereas what you want is to keep the low 32 bits of the answer. Probably the best way to is:

  • Write your own integer-power function, which takes arguments as Ints and calculates x^N for you by doing multiplication of x N times, and trusting the .NET runtime to be reasonably efficient (or if it's too slow, using some optimisation like doing exponentiation by squaring). Don't let the numbers grow too big, either by rounding off after each multiple using the remainder or bitwise-and operators, or using unchecked values and trusting them to wrap round and keep the low 32 bits each time.
  • Look for a library or existing code which calculates a CRC32 directly (eg. http://www.google.co.uk/search?q=c%23+crc32)

Upvotes: 2

Sebastian Mach
Sebastian Mach

Reputation: 39109

Those are powers, not xors. See Wikipedia about CRC.

Upvotes: 2

Related Questions