Возможно, я просто не вижу этого, но CRC32 кажется либо излишне сложным, либо недостаточно объясненным в любом месте, которое я мог найти в Интернете.
Я понимаю, что это остаток от арифметического деления значения сообщения, не основанного на переносе, деленный на полином (генератора), но его реальная реализация ускользает от меня.
Я прочитал «Безболезненное руководство по алгоритмам обнаружения ошибок CRC» и должен сказать, что это было не безболезненно. Это довольно хорошо проходит через теорию, но автор никогда не доходит до простого «вот оно». Он действительно говорит, каковы параметры для стандартного алгоритма 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;
}
но похоже, что это генерирует значения, несовместимые со значениями, которые я нашел в других местах в Интернете. Я мог бы использовать значения, которые нашел в Интернете, но я хочу понять, как они были созданы.
Мы будем очень благодарны за любую помощь в прояснении этих невероятно запутанных чисел .
0xEDB88320
также можно записать msbit-first ( нормальный ) как0x04C11DB7
. Были ли значения таблицы, которые вы нашли в другом месте, были сгенерированы с использованием того же полинома CRC?Ответы:
Полином для CRC32:
Или в шестнадцатеричном и двоичном формате:
Наивысший член (x 32 ) обычно явно не записывается, поэтому вместо этого он может быть представлен в шестнадцатеричном формате так же, как
Не стесняйтесь подсчитывать единицы и нули, но вы обнаружите, что они совпадают с полиномом, где
1
бит 0 (или первый бит) иx
бит 1 (или второй бит).Почему этот многочлен? Потому что должен быть стандарт заданного многочлена, а стандарт был установлен IEEE 802.3. Также чрезвычайно сложно найти многочлен, который эффективно обнаруживает различные битовые ошибки.
Вы можете думать о CRC-32 как о серии «двоичной арифметики без переносов» или, по сути, «операций XOR и сдвига». Технически это называется полиномиальной арифметикой.
Чтобы лучше понять это, представьте себе это умножение:
Если мы предположим, что x является основанием 2, мы получим:
Зачем? Поскольку 3x ^ 3 равно 11x ^ 11 (но нам нужна только 1 или 0 предварительная цифра), мы переносим:
Но математики изменили правила так, что это mod 2. Таким образом, в основном любой двоичный полином по модулю 2 - это просто сложение без переноса или XOR. Итак, наше исходное уравнение выглядит так:
Я знаю, что это прыжок веры, но это выходит за рамки моих возможностей как линейного программиста. Если вы заядлый студент или инженер в области компьютерных наук, я призываю вас разбить это на части. Этот анализ принесет пользу всем.
Итак, чтобы проработать полный пример:
Теперь мы разделим расширенное сообщение на Poly, используя арифметику CRC. Это то же деление, что и раньше:
Деление дает частное, которое мы отбрасываем, и остаток, который является вычисленной контрольной суммой. На этом расчет заканчивается. Обычно контрольная сумма затем добавляется к сообщению и передается результат. В этом случае передача будет: 11010110111110.
Используйте только 32-битное число в качестве делителя и используйте весь поток в качестве дивиденда. Выбросьте частное и оставьте остаток. Добавьте остаток в конец сообщения, и у вас будет CRC32.
Средний отзыв парня:
(Обратите внимание, что поток должен быть разделен на 32 бита или должен быть дополнен. Например, 8-битный поток ANSI должен быть дополнен. Также в конце потока деление останавливается.)
источник
x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 ... If we assume x is base 2 then we get: x^7 + x^3 + x^2 + x^1 + x^0
. Математика работает не так. Коэффициенты полинома равны mod (2) или GF (2), x остаются в покое, в результате получается x ^ 6 + x ^ 5 + x ^ 4 + x ^ 3 + x ^ 2 + x ^ 1 + x ^ 0 (поскольку 3 mod (2) = 1).Tack the remainder on the end of your message
- технически остаток вычитается из 0 битов, которые были добавлены к сообщению, но поскольку это математика mod (2), и сложение, и вычитание такие же, как XOR, а нулевые биты, XOR'ed с остатком, такие же как остаток.Why did you append four 0s though?
программные алгоритмы вычисления crc эффективно добавляют нули, хотя это не очевидно. Если вы показываете вычисление CRC с использованием длинного деления, то для правильного отображения примера деления необходимо добавить нули.Для IEEE802.3, CRC-32. Думайте обо всем сообщении как о последовательном потоке битов, добавьте 32 нуля в конец сообщения. Затем вы ДОЛЖНЫ поменять местами биты КАЖДОГО байта сообщения и добавить 1 к первым 32 битам. Теперь разделите на полином CRC-32, 0x104C11DB7. Наконец, вы должны добавить 1 к 32-битному остатку от этого деления, перевернув каждый из 4 байтов остатка. Это становится 32-битной CRC, которая добавляется в конец сообщения.
Причина этой странной процедуры в том, что первые реализации Ethernet сериализовали бы сообщение по одному байту за раз и сначала передавали младший бит каждого байта. Затем последовательный поток битов прошел через последовательное вычисление регистра сдвига CRC-32, которое было просто дополнено и отправлено по сети после завершения сообщения. Причина дополнения первых 32 бита сообщения заключается в том, чтобы вы не получили CRC полностью нулевым, даже если сообщение было полностью нулями.
источник
CRC довольно прост; вы берете многочлен, представленный как биты и данные, и делите многочлен на данные (или вы представляете данные как многочлен и делаете то же самое). Остаток, который находится между 0 и полиномом, является CRC. Ваш код немного сложен для понимания, отчасти потому, что он неполный: temp и testcrc не объявлены, поэтому неясно, что индексируется и сколько данных проходит через алгоритм.
Способ понять CRC - это попытаться вычислить несколько, используя короткий фрагмент данных (16 бит или около того) с коротким полиномом - возможно, 4 бита. Если вы попрактикуетесь таким образом, вы действительно поймете, как можно его кодировать.
Если вы делаете это часто, CRC довольно медленно вычисляется программным обеспечением. Аппаратные вычисления намного более эффективны и требуют всего несколько вентилей.
источник
В дополнение к статьям « Проверка циклическим избыточным кодом» и « Вычисление CRC» в Википедии , я нашел хорошим справочником документ под названием Reversing CRC - Theory and Practice * .
По сути, существует три подхода к вычислению CRC: алгебраический подход, бит-ориентированный подход и подход, управляемый таблицами. В обращении CRC - теория и практика * каждый из этих трех алгоритмов / подходов объясняется теоретически и сопровождается в ПРИЛОЖЕНИИ реализацией CRC32 на языке программирования C.
* PDF Link
Reversing CRC - Теория и практика.
Публичный отчет Берлинского университета
SAR-PR-2006-05,
май 2006 г.
Авторы:
Мартин Стигге, Хенрик Плётц, Вольф Мюллер, Йенс-Петер Редлих
источник
Я потратил некоторое время, пытаясь найти ответ на этот вопрос, и, наконец, сегодня опубликовал учебное пособие по CRC-32: руководство по хешированию CRC-32 - AutoHotkey Community
В этом примере я демонстрирую, как вычислить хэш CRC-32 для строки ASCII 'abc':
источник
^
? stackoverflow.com/questions/62168128/…Затем всегда есть Rosetta Code, который показывает, что crc32 реализован на десятках компьютерных языков. https://rosettacode.org/wiki/CRC-32 и содержит ссылки на множество объяснений и реализаций.
источник
Чтобы уменьшить crc32 до приема напоминаний, вам необходимо:
В коде это:
где напоминаниеIEEE - чистое напоминание о GF (2) [x]
источник