2

我下载了一个文件和他的校验和(由 cksum Unix 命令生成)。

所以,我想在我的 C# 应用程序测试中校验和是否与我下载的应用程序足够。

我查看了 chsum 的 Unix 手册页:

  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.

所以我写了一个简单的程序来求和:

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);
}

但是校验和不一样,我该如何解决这个问题?

谢谢


编辑

1)修改后的算法为:

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)我用class Crc32 : HashAlgorithm

给定一个 Unix 文件,其中 Crc32 为:2774111254

  • 1)给我:4243613712
  • 2)给我:3143134679(种子为0)

我做错了什么!?

4

4 回答 4

2

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)
于 2011-07-12T08:49:39.373 回答
2

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

于 2011-07-12T08:49:47.963 回答
2

另请参阅此正确实现https://cksum.codeplex.com/

于 2014-10-07T00:24:07.713 回答
2

这些是权力,而不是异或。请参阅有关 CRC 的维基百科

于 2011-07-12T08:41:00.417 回答