2010-04-06 7 views
70

Возможно, я просто не вижу этого, но CRC32 кажется либо излишне сложным, либо недостаточно объясненным где угодно, что я могу найти в Интернете.Как рассчитывается контрольная сумма CRC32?

Я понимаю, что это остаток от арифметического деления на основе переноса, не связанного с переносом, поделенного на (генератор) многочлен, но фактическая реализация его ускользает от меня.

Я читал A Painless Guide To CRC Error Detection Algorithms, и должен сказать, что это было безболезненно. Он довольно хорошо разбирается в теории, но автор никогда не доходит до простого «это он». Он говорит, что параметры для стандартного алгоритма CRC32, но он пренебрегает четко излагать, как вы к нему обращаетесь.

Часть, которая меня получает, когда он говорит «это она», а затем добавляет: «о, кстати, ее можно отменить или начать с разных начальных условий» и не дает ясного ответа какой последний способ расчета контрольной суммы CRC32 дал все изменения, которые он только что добавил.

  • Есть ли более простое объяснение того, как рассчитывается CRC32?

Я попытался код в C, как формируется таблица:

for (i = 0; i < 256; i++) 
{ 
    temp = i; 

    for (j = 0; j < 8; j++) 
    { 
     if (temp & 1) 
     { 
      temp >>= 1; 
      temp ^= 0xEDB88320; 
     } 
     else {temp >>= 1;} 
    } 
    testcrc[i] = temp; 
} 

, но это, кажется, генерировать значения, несовместимые с ценностями я нашел в другом месте в Интернете. I может использовать значения, которые я нашел в Интернете, но я хочу понять, как они были созданы.

Любая помощь в расчистке этих невероятно запутанных номеров будет очень оценена.

+5

Ваш код для генерации таблицы CRC32 выглядит правильно. Ваш lsbit-first (* reverseed *) CRC32-многочлен '0xEDB88320' также может быть записан в msbit-first (* normal *) как' 0x04C11DB7'. Были ли значения таблиц, найденные вами в другом месте, с использованием одного и того же полинома CRC? – jschmier

ответ

7

CRC довольно прост; вы берете многочлен, представляемый как биты и данные, и делите полином на данные (или вы представляете данные как многочлен и делаете то же самое). Остаток, который находится между 0 и многочленом, является CRC. Ваш код немного сложно понять, отчасти потому, что он неполный: temp и testcrc не объявлены, поэтому неясно, что индексируется, и сколько данных выполняется через алгоритм.

Способ понять CRC состоит в том, чтобы попытаться вычислить несколько, используя короткую часть данных (16 бит или около того) с коротким многочленом - возможно, 4 бита. Если вы практикуете этот путь, вы действительно поймете, как вы можете его кодировать.

Если вы делаете это часто, CRC довольно медленно вычисляет в программном обеспечении. Аппаратное вычисление намного более эффективно и требует всего нескольких ворот.

74

Полином для CRC32 является:

0x 04 С1 1D B7

х + X + X + X + х + x + x + x + x + х + х + х + х + 1

, который работает, чтобы быть в двоичном виде:

Вы можете считать 1 и 0, но вы увидите, что они совпадают с многочленом, где 1 является бит 0 (или первый бит) и x является бит 1 (или второй бит).

Почему этот многочлен? Потому что должен быть стандартный заданный полином, и стандарт был установлен IEEE 802.3. Также чрезвычайно сложно найти многочлен, который эффективно обнаруживает различные битовые ошибки.

Вы можете думать о CRC-32 как о серии «Двоичная арифметика без несушек» или в основном «XOR и операции сдвига». Это технически называется полиномиальной арифметикой.

Чтобы лучше понять это, думает, это умножение:

(x^3 + x^2 + x^0)(x^3 + x^1 + x^0) 
= (x^6 + x^4 + x^3 
+ x^5 + x^3 + x^2 
+ x^3 + x^1 + x^0) 
= x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 

Если предположить й основание 2, то мы получим:

x^7 + x^3 + x^2 + x^1 + x^0 

Почему? Поскольку 3x^3 является 11x^11 (но нам нужно только 1 или 0 до цифры), поэтому перенесет:

=1x^110 + 1x^101 + 1x^100   + 11x^11 + 1x^10 + 1x^1 + x^0 
=1x^110 + 1x^101 + 1x^100 + 1x^100 + 1x^11 + 1x^10 + 1x^1 + x^0 
=1x^110 + 1x^101 + 1x^101   + 1x^11 + 1x^10 + 1x^1 + x^0 
=1x^110 + 1x^110     + 1x^11 + 1x^10 + 1x^1 + x^0 
=1x^111       + 1x^11 + 1x^10 + 1x^1 + x^0 

Но математики изменили правила так, что модуль 2. Таким образом, в основном любой двоичный полином по модулю 2 это просто дополнение без переноса или XOR.Таким образом, наше исходное уравнение выглядит следующим образом:

=(1x^110 + 1x^101 + 1x^100 + 11x^11 + 1x^10 + 1x^1 + x^0) MOD 2 
=(1x^110 + 1x^101 + 1x^100 + 1x^11 + 1x^10 + 1x^1 + x^0) 
= x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 (or that original number we had) 

Я знаю, что это прыжок веры, но это за пределами моей способности как линии-программист. Если вы являетесь основателем CS-студент или инженером, я бросаю вызов сломать это. Этот анализ будет полезен всем.

Так отработать полный пример:

Original message    : 1101011011 
    Polynomial of (W)idth 4   :  10011 
    Message after appending W zeros : 11010110110000 

Теперь разобьет дополненное сообщение в Poly с использованием CRC арифметики. Это же разделение, как и раньше:

  1100001010 = Quotient (nobody cares about the quotient) 
     _______________ 
10011) 11010110110000 = Augmented message (1101011011 + 0000) 
=Poly 10011,,.,,.... 
     -----,,.,,.... 
     10011,.,,.... 
     10011,.,,.... 
     -----,.,,.... 
      00001.,,.... 
      00000.,,.... 
      -----.,,.... 
      00010,,.... 
      00000,,.... 
      -----,,.... 
      00101,.... 
      00000,.... 
      -----,.... 
      01011.... 
      00000.... 
      -----.... 
       10110... 
       10011... 
       -----... 
       01010.. 
       00000.. 
       -----.. 
       10100. 
       10011. 
       -----. 
       01110 
       00000 
       ----- 
        1110 = Remainder = THE CHECKSUM!!!! 

Разделение дает фактор, который мы выбрасываем, а остаток, который вычисленная контрольная сумма. Это завершает расчет. Обычно контрольная сумма добавляется к сообщению и передается результат. В этом случае передача будет: 11010110111110.

Используйте только 32-битное число в качестве делителя и использовать весь поток в качестве дивидендов. Выбросьте фактор и сохраните остаток. Отложите остаток в конце вашего сообщения, и у вас есть CRC32.

Средняя оценка парень:

  QUOTIENT 
     ---------- 
DIVISOR) DIVIDEND 
       = REMAINDER 
  1. Возьмите первые 32 бита.
  2. сдвига битов
  3. Если 32 бит меньше, чем DIVISOR, перейти к шагу 2.
  4. исключающее 32 битов с помощью DIVISOR. Перейдите к шагу 2.

(Обратите внимание, что поток должен быть разделен на 32 бита или должен быть дополнен. поток, деление прекращается.)

+9

+1 для «Среднего просмотра парня» в конце - возможно, подумайте о том, чтобы переместить это право на верхнюю панель - своего рода TL; DR: P – aaronsnoswell

+0

почему XOR используется вместо вычитания в части с длинным разделением? пожалуйста, объясните – abstractnature

+1

@abstractnature Помните, что мы делим многочлены, а не только двоичные числа. Мы не можем делать «нормальное» вычитание, потому что мы не можем «заимствовать» $ x^n $ из $ x^{n + 1} $; это разные вещи. Кроме того, поскольку бит равен только 0 или 1, что бы было -1 даже? Действительно, мы работаем в кольце полиномов с коэффициентами в поле $ Z/2Z $, которое имеет только два элемента: 0 и 1 и где $ 1 + 1 = 0 $. Полагая коэффициенты в поле, полиномы образуют то, что называется евклидовой областью, что в основном просто позволяет то, что мы пытаемся сделать, чтобы быть четко определенным в первую очередь. – calavicci

6

в дополнение к Википедии Cyclic redundancy check и Computation of CRC статей, я нашел документ, озаглавленный Reversing CRC - Theory and Practice* быть хорошим справочником.

Существует, по существу, три подхода к вычислению CRC: алгебраический подход, битоориентированный подход и подход, основанный на таблицах. В Reversing CRC - Theory and Practice* каждый из этих трех алгоритмов/подходов объясняется в теории, сопровождаемой в ПРИЛОЖЕНИИ реализацией для CRC32 на языке программирования C.

* PDF Ссылка
реверса CRC - теория и практика.
HU Berlin Открытый отчет
SAR-PR-2006-05
мая 2006
Авторы:
Мартин Stigge, Генрик Plotz, Вольф Мюллер, Jens-Peter Редлих

3

Для IEEE802.3, CRC-32. Подумайте обо всем сообщении в виде последовательного потока бит, добавьте 32 нулей в конец сообщения. Затем вы ДОЛЖНЫ развернуть биты КАЖДОГО байт сообщения и сделать дополнение 1 к первым 32 битам. Теперь разделим на многочлен CRC-32, 0x104C11DB7. Наконец, вы должны дополнить 32-битный остаток этого деления на бит-реверс каждого из 4 байтов остатка. Это становится 32-разрядным CRC, который добавляется к концу сообщения.

Причина этой странной процедуры заключается в том, что первые реализации Ethernet будут сериализовать сообщение по одному байту за раз и сначала передать младший значащий бит каждого байта. Последовательный бит-поток затем прошел последовательный CRC-32 сдвиговый регистр, который был просто дополнен и отправлен на провод после того, как сообщение было завершено. Причина для дополнения первых 32 бит сообщения заключается в том, что вы не получите нулевой CRC, даже если сообщение было нулевым.

+0

Это лучший ответ на данный момент, хотя я бы заменил «бит-реверс каждого из 4 байтов» на «бит» -изменить 4 байта, рассматривая их как одну сущность ', например 'abcdefgh ijklmnop qrstuvwx yzABCDEF' to 'FEDCBAzy xwvutsrq ponmlkji hgfedcba'. См. Также: [Учебное пособие по CRC-32 - Сообщество AutoHotkey] (https://autohotkey.com/boards/viewtopic.php?f=7&t=35671). – vafylec

0

я провел некоторое время, пытаясь раскрыть ответ на этот вопрос, и я, наконец, опубликовал учебник по CRC-32 сегодня: CRC-32 hash tutorial - AutoHotkey Community

В этом примере из него, я продемонстрирую, как вычислить CRC-32 хэш для строки ASCII 'abc':

calculate the CRC-32 hash for the ASCII string 'abc': 

inputs: 
dividend: binary for 'abc': 0b011000010110001001100011 = 0x616263 
polynomial: 0b100000100110000010001110110110111 = 0x104C11DB7 

011000010110001001100011 
reverse bits in each byte: 
100001100100011011000110 
append 32 0 bits: 
10000110010001101100011000000000000000000000000000000000 
XOR the first 4 bytes with 0xFFFFFFFF: 
01111001101110010011100111111111000000000000000000000000 

'CRC division': 
01111001101110010011100111111111000000000000000000000000 
100000100110000010001110110110111 
--------------------------------- 
    111000100010010111111010010010110 
    100000100110000010001110110110111 
    --------------------------------- 
    110000001000101011101001001000010 
    100000100110000010001110110110111 
    --------------------------------- 
    100001011101010011001111111101010 
    100000100110000010001110110110111 
    --------------------------------- 
     111101101000100000100101110100000 
     100000100110000010001110110110111 
     --------------------------------- 
      111010011101000101010110000101110 
      100000100110000010001110110110111 
      --------------------------------- 
      110101110110001110110001100110010 
      100000100110000010001110110110111 
      --------------------------------- 
      101010100000011001111110100001010 
      100000100110000010001110110110111 
      --------------------------------- 
       101000011001101111000001011110100 
       100000100110000010001110110110111 
       --------------------------------- 
       100011111110110100111110100001100 
       100000100110000010001110110110111 
       --------------------------------- 
        110110001101101100000101110110000 
        100000100110000010001110110110111 
        --------------------------------- 
        101101010111011100010110000001110 
        100000100110000010001110110110111 
        --------------------------------- 
         110111000101111001100011011100100 
         100000100110000010001110110110111 
         --------------------------------- 
         10111100011111011101101101010011 

remainder: 0b10111100011111011101101101010011 = 0xBC7DDB53 
XOR the remainder with 0xFFFFFFFF: 
0b01000011100000100010010010101100 = 0x438224AC 
reverse bits: 
0b00110101001001000100000111000010 = 0x352441C2 

thus the CRC-32 hash for the ASCII string 'abc' is 0x352441C2 
Смежные вопросы