Эквивалентен Unix cksum в Windows

Я скачиваю файл и его контрольную сумму (сгенерированную командой Unix cksum).

Итак, я хочу в своем приложении C # проверить, соответствует ли контрольная сумма загруженному мной приложению.

Я проверил на странице руководства Unix 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.

Итак, я написал простую программу, которая вычисляет сумму:

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)

Что делаю не так !?


person Arnaud F.    schedule 12.07.2011    source источник
comment
Для реализации crc32 на C # проверьте stackoverflow.com/q/4656659/11343   -  person CharlesB    schedule 12.07.2011


Ответы (4)


В C # символ ^ является оператором «исключающее ИЛИ». Вам нужна функция Math.Pow.

Это дает количество двух чисел с плавающей запятой, альтернативные варианты предлагаются на странице Как сделать вы делаете * целочисленное * возведение в степень на 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

person James Wiseman    schedule 12.07.2011
comment
Я пробовал класс, предоставленный вашей ссылкой, но не получил того же результата. Unix: >cksum file2.exe : 2774111254; Crc32.Compute(arr);: 1514701405; и предыдущий код исправлен с помощью Pow: 4243613712. Чем они отличаются? - person Arnaud F.; 12.07.2011

Это полномочия, а не xors. См. Википедию о CRC.

person Sebastian Mach    schedule 12.07.2011

В С # ^ - это не оператор возведения в степень, а оператор xor, тогда как CRC написан с использованием общей математической терминологии, не специфичной для какого-либо языка.

Не используйте стандартную функцию "pow", поскольку они обычно используют плавающую точку для представления очень больших чисел, таких как x ^ 32.

В то время как вы хотите сохранить низкие 32 бита ответа. Наверное, лучший способ:

  • Напишите свою собственную целочисленную степенную функцию, которая принимает аргументы как Ints и вычисляет x ^ N для вас, выполняя умножение x N раз и полагаясь на то, что среда выполнения .NET будет достаточно эффективной (или, если она слишком медленная, используя некоторую оптимизацию, например выполнение возведение в степень квадратом). Не позволяйте числам становиться слишком большими, либо округляя после каждого кратного с использованием остатка или побитовых операторов и, либо используя непроверенные значения и доверяя им оборачивание и сохранение младших 32 бита каждый раз.
  • Найдите библиотеку или существующий код, который вычисляет CRC32 напрямую (например, http://www.google.co.uk/search?q=c%23+crc32)
person Jack V.    schedule 12.07.2011

См. Также правильную реализацию https://cksum.codeplex.com/

person Carlos Rendon    schedule 07.10.2014