Что такое контрольная сумма CRC?
Циклический избыточный код (CRC, Cyclic Redundancy Check) — это код обнаружения ошибок, который широко применяется в сетях, накопителях и форматах файлов (Ethernet, ZIP, PNG, Modbus, USB и многих других). Алгоритм рассматривает ваши данные как одно большое двоичное число и делит его на фиксированный порождающий полином по правилам двоичной арифметики без переносов (поле GF(2), где сложение и вычитание — это операция XOR). Остаток от такого деления и есть CRC. Если меняется хотя бы один бит сообщения, остаток почти всегда тоже меняется — именно поэтому CRC так хорошо ловит ошибки при передаче и хранении данных.
Как пользоваться калькулятором
Введите любой текст в кодировке ASCII в поле ввода, выберите нужный вариант CRC и посмотрите результат. Инструмент показывает контрольную сумму одновременно в шестнадцатеричном и десятичном виде, а также разрядность и количество обработанных байт. Поддерживаются три самых распространённых варианта:
$$\text{CRC} = \mathrm{XorOut} \oplus \bigoplus_{b \in \text{Message bytes}} \mathrm{Update}_{\text{poly}}(\text{crc}, b)$$
$$\text{где (CRC-16/CCITT-FALSE)}\quad \left\{ \begin{aligned} \text{poly} &= \mathtt{0x1021} \\ \mathrm{init} &= \mathtt{0xFFFF} \\ \mathrm{XorOut} &= \mathtt{0x0000} \\ \text{width} &= 16 \text{ bits (MSB-first, no reflection)} \end{aligned} \right.$$
CRC-8 — полином \(\mathtt{0x07}\), начальное значение \(\mathtt{0x00}\).
CRC-16/CCITT-FALSE — полином \(\mathtt{0x1021}\), начальное значение \(\mathtt{0xFFFF}\), без отражения битов.
CRC-32 (IEEE 802.3) — отражённый полином \(\mathtt{0xEDB88320}\), начальное значение \(\mathtt{0xFFFFFFFF}\), финальный XOR \(\mathtt{0xFFFFFFFF}\). Именно этот вариант используется в ZIP, gzip и Ethernet.
Разбор формулы
По сути сообщение \(M(x)\) умножается на \(x^n\) (где \(n\) — степень порождающего полинома) и делится на \(G(x)\). На практике используется регистр, который сдвигается по одному биту за раз, и в него выполняется XOR с полиномом всякий раз, когда старший бит равен 1. В отражённых вариантах (как CRC-32) биты обрабатываются начиная с младшего, а сдвиг выполняется вправо, а не влево.
$$\text{CRC}_{16} = \bigoplus_{b \in \text{Message bytes}} \mathrm{Update}(\text{crc}, b)$$
$$\text{где}\quad \left\{ \begin{aligned} \mathrm{init} &= \mathtt{0xFFFF} \\ \text{poly} &= \mathtt{0x1021} \\ \text{step} &: \text{crc} \leftarrow \big(\text{crc} \ll 1\big) \oplus (\text{MSB}?\,\text{poly}:0) \\ \text{width} &= 16 \text{ bits, MSB-first} \end{aligned} \right.$$
$$\text{CRC}_{8} = \bigoplus_{b \in \text{Message bytes}} \mathrm{Update}(\text{crc}, b)$$
$$\text{где}\quad \left\{ \begin{aligned} \mathrm{init} &= \mathtt{0x00} \\ \text{poly} &= \mathtt{0x07} \\ \text{step} &: \text{crc} \leftarrow \big(\text{crc} \ll 1\big) \oplus (\text{MSB}?\,\text{poly}:0) \\ \text{width} &= 8 \text{ bits, MSB-first} \end{aligned} \right.$$
$$\text{CRC}_{32} = \mathtt{0xFFFFFFFF} \oplus \bigoplus_{b \in \text{Message bytes}} \mathrm{Update}(\text{crc}, b)$$
$$\text{где}\quad \left\{ \begin{aligned} \mathrm{init} &= \mathtt{0xFFFFFFFF} \\ \text{poly} &= \mathtt{0xEDB88320}\ (\text{reflected}) \\ \text{step} &: \text{crc} \leftarrow \big(\text{crc} \gg 1\big) \oplus (\text{LSB}?\,\text{poly}:0) \\ \text{width} &= 32 \text{ bits, LSB-first} \end{aligned} \right.$$
Пример расчёта
Для классической проверочной строки 123456789: CRC-16/CCITT-FALSE даёт 0x29B1 (\(10673\) в десятичном виде), а CRC-32/IEEE — 0xCBF43926 (\(3421780262\) в десятичном виде). Это стандартные «проверочные» значения, опубликованные в справочниках по CRC, поэтому по ним можно сверить корректность любой реализации.
Частые вопросы
Почему мой результат отличается от другого калькулятора? Варианты CRC различаются полиномом, начальным значением, отражением битов и финальным XOR. Убедитесь, что вы сравниваете один и тот же вариант.
Является ли CRC надёжным хешем? Нет. CRC обнаруживает случайные ошибки, но его легко подделать намеренно. Для безопасности используйте SHA-256 или аналогичные алгоритмы.
Какая кодировка используется? Каждый символ берётся как его 8-битное байтовое значение ASCII/Latin-1, и уже после этого вычисляется CRC.