Проверка контрольной суммы CRC против нуля - PullRequest
1 голос
/ 15 октября 2019

У меня был некоторый контакт с контрольной суммой CRC-16 в прошлом, и я привык проверять ее путем пересчета контрольной суммы CRC-16 по файлу, который я хочу проверить, плюс 2 байта самой CRC-16. Если результат был нулевым, то целостность файла была действительной, в противном случае - нет.

Это может быть очень эффективно закодировано, как с помощью следующего псевдо-C:

if (recalculated_crc16_checksum != 0) // Error: file integrity is corrupt else // Success: file integrity is valid

Недавно я хотел использовать контрольную сумму CRC-32 для проверки целостности файла и пытался проверить ее таким же образом, но кажется, что этот «Сравнение с нулевым трюком» здесь невозможен?!

Например, если я использую 32-битное значение 0xDEADBEEF в онлайн-калькуляторе CRC:

CRC-16-Modbus(0xDEADBEEF) = 0xC19B (Same input value but with appended checksum 0xC19B in reversed byte ordering) CRC-16-Modbus(0xDEADBEEF9BC1) = 0x0000

Но:

CRC-32(0xDEADBEEF) = 0x7C9CA35A (I tried both: big and little endian byte ordering for the appended checksum) CRC-32(0xDEADBEEF7C9CA35A) = 0x01F92292 != 0x00000000 CRC-32(0xDEADBEEF5AA39C7C) = 0x2144DF1C != 0x00000000

Может кто-нибудь объяснить, почему этот «Сравнение с нулевым трюком» не работает для CRC-32?

1 Ответ

6 голосов
/ 15 октября 2019

Проблема не в том, что CRC является 32-битным, а в том, что CRC является посткомплементарным, xorout = 0xffffffff. Если вы добавите CRC (little-endian) к сообщению, а затем снова вычислите CRC, если ошибок нет, CRC всегда будет 0x2144DF1C. Таким образом, в этом случае вы проверяете CRC против 0x2144DF1C.

Вы можете найти этот онлайн-калькулятор CRC немного более информативным, поскольку он показывает параметры: polynomial, xorin, xorout.

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

Чтобы объяснить, что происходитобычно, если вы вычисляете и добавляете несопоставленный CRC к сообщению, а затем вычисляете CRC сообщения + CRC, результирующий CRC равен нулю (если ошибок нет). Пусть CRC32X = пользовательский CRC32 с начальным значением = 0 и xorout = 0. Вы можете скопировать и вставить данные ниже с помощью онлайн-калькулятора CRC, на который я разместил ссылку.

CRC32X{0x31 0x32 0x33 0x34} = 0xBAA73FBF

добавление CRC и повторный расчет:

CRC32X{0x31 0x32 0x33 0x34 0xBF 0x3F 0xA7 0xBA} = 0x00000000

Теперь рассмотрим более простой случай:

CRC32X{0x00 0x00 0x00 0x00} = 0x00000000
CRC32X{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} = 0x00000000

Затем, чтобы увидеть эффект дополнения CRC идобавив его:

CRC32X{0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF} = 0xDEBB20E3

и взяв дополнение (используя ~ для не):

~CRC32X{0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF} = ~0xDEBB20E3 = 0x2144DF1C

Начальное значение XOR 'с первыми 4 байтами сообщения. Таким образом, для CRC32 () с начальным значением 0xFFFFFFFF и пост-дополненным CRC:

 CRC32(0x00 0x00 0x00 0x00) = 0x2144DF1C 
~CRC32X(0xFF 0xFF 0xFF 0xFF) = ~0xDEBB20E3 = 0x2144DF1C
...