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 : 277411125开发者_如何转开发4
- 1) Gives me : 4243613712
- 2) Gives me : 3143134679 (with a seed of 0)
What I'm doing wrong !?
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
Those are powers, not xors. See Wikipedia about CRC.
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)
Also see this correct implementation https://cksum.codeplex.com/
精彩评论