相当于Windows中的Unix cksum

时间:2011-07-12 08:27:50

标签: c# checksum crc32

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

所以,我希望,在我的C#app测试中,Checksum是否与我下载的应用程序相符。

我查看了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 个答案:

答案 0 :(得分:2)

这些是权力,而不是xors。请参阅Wikipedia about CRC

答案 1 :(得分:2)

在c#中,^不是一个升级到幂的运算符,而是一个xor运算符,而CRC是使用不特定于任何语言的通用数学术语编写的。

不要使用标准的“pow”函数,因为它们通常会使用浮点来表示非常大的数字,例如x ^ 32。

而你想要的是保持 32位的答案。可能最好的方法是:

  • 编写自己的整数幂函数,它将参数作为Ints并通过x次乘法计算x ^ N,并信任.NET运行时效率相当(或者如果它太慢,使用一些优化就像通过平方进行取幂)。不要让数字变得太大,要么通过使用余数或按位运算符在每个倍数之后进行四舍五入,要么使用未经检查的值并信任它们以包围并且每次保持低32位。
  • 查找直接计算CRC32的库或现有代码(例如http://www.google.co.uk/search?q=c%23+crc32

答案 2 :(得分:2)

在C#中,^符号是独占或运算符。您需要函数Math.Pow

这为piower提供了两个浮点数,在How do you do *integer* exponentiation in C#?

建议使用替换

因此,您的代码看起来像:

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

还要注意最后一句话:

  

计算结果被截断为32位值。该   还会打印文件中的字节数。

是签名(int)还是未签名(uint

你当然可以使用以下内容: http://www.codeproject.com/Articles/35134/How-to-calculate-CRC-in-C

答案 3 :(得分:0)

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