CRC32 рассчитан неправильно

Я использую очень простой алгоритм для вычисления CRC32, но он дает неправильные значения.

Я сравниваю свои выходные значения с данными калькулятора, но они всегда выглядят по-разному.

unsigned int crc32_tab[256] = {
        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
        0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
        0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
      .........,..............,.............,.........,...........
    };

Функция, использующая таблицу поиска,

 unsigned int MyClass::crc32(unsigned int crc, const void *buf, unsigned int   size)
{
const unsigned int *p;

p = (const quint8 *)buf;
crc = crc ^~ 0xFFFFFFFF;

while(size--)
{
    crc = this->crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}

return crc ^~ 0xFFFFFFFF;
}

Я называю это так

 QString test= QString::number(mclass.crc32(0, crcval, 6))

person tulipe    schedule 05.07.2015    source источник
comment
Помимо любых реальных проблем, которые могут быть или не быть в вашем коде, что именно делает ^~ 0xFFFFFFFF?   -  person Iwillnotexist Idonotexist    schedule 05.07.2015
comment
На самом деле этот шаг не имеет никакого значения, так как если бит с нулевым значением останется равным 0, а если 1, то он останется таким же.   -  person tulipe    schedule 05.07.2015
comment
Это была именно моя точка зрения. Вы выполняете XOR с дополнением всех единиц, то есть со всеми нулями, то есть ничего не делаете. Если вы намеревались дополнить биты, вам следует использовать x = ~x;. Что касается остальной части вашего кода, вы уверены, что он не вычисляет бит-обратный результат? Использование правильного полинома (CRC-32/Ethernet по сравнению с CRC-32C/Castagnoli)?   -  person Iwillnotexist Idonotexist    schedule 05.07.2015
comment
Калькулятор, который вы используете, похоже, использует полином генератора Ethernet CRC-32.   -  person Iwillnotexist Idonotexist    schedule 05.07.2015
comment
Да, я использовал его, но использует ли другой калькулятор другой CRC-32? В чем разница между ними?   -  person tulipe    schedule 05.07.2015
comment
Единого CRC-32 не существует. На самом деле существует целое семейство алгоритмов CRC-32, каждый из которых отличается своим порождающим полиномом. Другой полином генератора, конечно, означает, что они производят разные контрольные суммы для одних и тех же данных, и что их реализация будет использовать разные значения таблицы поиска. Двумя наиболее популярными алгоритмами CRC-32, вероятно, являются CRC-32 (Ethernet, генераторный полином 0x04C11DB7) и CRC-32C (Castagnoli, 0x1EDC6F41).   -  person Iwillnotexist Idonotexist    schedule 05.07.2015
comment
Я использую Ethernet один, и я думаю, что калькулятор, который я использовал в качестве эталона, использует его. Я прав?   -  person tulipe    schedule 05.07.2015
comment
Давайте продолжим обсуждение в чате.   -  person tulipe    schedule 05.07.2015
comment
Почему это помечено как qt?   -  person Hamish Moffatt    schedule 06.07.2015
comment
@HamishMoffatt Вероятно, потому, что рассматриваемый код вызывается из приложения Qt C++. Однако, учитывая, что проблема не имеет ничего общего с Qt/не Qt-приложением, я бы, вероятно, переименовал его [c++] плюс любые другие соответствующие теги.   -  person Iwillnotexist Idonotexist    schedule 06.07.2015


Ответы (1)


Решение взято из обсуждения в чате

Реализуемый алгоритм CRC-32 представляет собой CRC-32 Ethernet (порождающий полином 0x04C11DB7).

Этот CRC-32 требует:

  • Будучи инициализированным с 0xFFFFFFFF.
  • И завершается с помощью операции XOR с 0xFFFFFFFF.

Таким образом, вы должны удалить операторы crc ^~ 0xFFFFFFFF в своей функции, передать 0xFFFFFFFF при вызове функции, и как только вы закончите CRC данных, вы должны XOR возвращаемого значения с 0xFFFFFFFF.

person Iwillnotexist Idonotexist    schedule 05.07.2015