Перейти к содержанию

Контрольная сумма (checksum)

Байт, пришедший по проводу или прочитанный из флеш-памяти, мог исказиться. Чтобы это заметить, передатчик вычисляет по данным короткое число и отправляет его вместе с ними, а приёмник считает его заново и сравнивает. Это число и называют контрольной суммой.

Обновлено Редакция GAW

Контрольная сумма (checksum) — короткое значение, которое вычисляют по блоку данных и передают или хранят вместе с ним, чтобы потом обнаружить искажение. Приёмник пересчитывает значение по полученным данным: не совпало — данные испорчены. В узком смысле так называют именно арифметические суммы байтов, в широком — любой проверочный код, включая CRC.

Простые суммы

Сумма по модулю 256. Все байты складываются, переносы отбрасываются, остаётся один байт. Его передают как есть или в виде дополнения, чтобы сумма всего пакета вместе с ним давала ноль.

LRC в Modbus ASCII. Спецификация Modbus по последовательной линии (разд. 2.5.2.2) задаёт её точно: сложить байты сообщения без переносов и взять дополнение до двух. Считают по двоичным байтам до кодирования в символы и без двоеточия в начале и CR LF в конце. Например, для байтов 01 03 00 00 00 0A сумма 0x0E, LRC = 0xF2.

Internet checksum (RFC 1071). Байты объединяют в 16-битные слова и складывают в обратном коде — перенос из старшего разряда добавляется к младшему. В поле записывают инверсию суммы; при проверке сумма по всему заголовку вместе с этим полем даёт все единицы. По RFC 1071 её используют стандартные протоколы IP, UDP и TCP.

Сумма или CRC

Сумма байтовCRC
Вычислениесложениеделение многочленов
Перестановка байтовне замечаеткак правило, замечает
Два ошибочных байта, компенсирующих друг другане замечаеткак правило, замечает
Гарантия обнаружениянеттолько в пределах расстояния Хэмминга и длины пачки ошибок для данного полинома и длины данных
Стоимостьминимальнаятаблица или сдвиги

Modbus поэтому разделяет режимы: текстовый ASCII защищён LRC, двоичный RTU — CRC-16 (для CRC-16/MODBUS контрольное значение строки «123456789» — 0x4B37 по каталогу Грега Кука). Похожая идея на уровне одного символа — бит чётности.

Где встречается

В заголовках сетевых пакетов, в строках файлов прошивки Intel HEX, в кадрах датчиков вроде DHT22, в собственных протоколах поверх UART. Как выбрать проверку для своего кадра и проверить её в тестах — в статье о реализации протоколов; посчитать CRC с любыми параметрами можно в калькуляторе CRC.

Частые вопросы

Чем контрольная сумма отличается от CRC?

В широком смысле CRC — тоже контрольная сумма, но вычисляется она делением многочленов, а не сложением. Простая сумма байтов не замечает перестановку байтов и многие парные ошибки, когда один байт увеличился, а другой уменьшился на столько же. CRC такие ошибки, как правило, ловит, а гарантированно обнаруживает ошибки в пределах своего расстояния Хэмминга и длины пачки для выбранного полинома и длины данных. Modbus RTU использует CRC-16, а простую LRC оставил для текстового режима ASCII.

Как посчитать LRC для Modbus ASCII?

Сложить все байты сообщения — адрес, функцию и данные — по модулю 256, отбрасывая переносы, а затем взять дополнение до двух: LRC = (−сумма) mod 256. Считают по двоичным байтам до их кодирования в шестнадцатеричные символы, без начального двоеточия и без CR LF. Для байтов 01 03 00 00 00 0A сумма равна 0x0E, LRC — 0xF2.

Почему в Internet checksum используют сложение в обратном коде?

У него есть удобные свойства, перечисленные в RFC 1071: результат не зависит от порядка байтов в слове, поэтому машины с разной архитектурой считают одинаково, а при изменении одного поля сумму можно пересчитать без прохода по всему пакету. Проверка тоже проста: сумма вместе с полем контрольной суммы даёт все единицы.

Источники

  1. R. Braden, D. Borman, C. Partridge. RFC 1071: Computing the Internet Checksum, September 1988 — соседние байты объединяются в 16-битные слова и складываются в обратном коде (с циклическим переносом); для формирования поле суммы обнуляют, считают сумму и записывают её инверсию; при проверке сумма по тем же байтам вместе с полем суммы должна дать все единицы; сумму можно считать в любом порядке байтов
  2. Modbus Organization. MODBUS over Serial Line Specification and Implementation Guide V1.02, 2006 — разд. 2.5.2.2: в режиме ASCII поле LRC — один байт; LRC считают сложением байтов сообщения без переносов и дополнением результата до двух, по байтам до кодирования в ASCII, без начального двоеточия и завершающих CR LF; разд. 2.5.1.2: в режиме RTU используется CRC-16
  3. G. Cook. Catalogue of parametrised CRC algorithms with 16 bits, reveng.sourceforge.io, обновлено 11 декабря 2024 — CRC-16/MODBUS: poly 0x8005, init 0xFFFF, refin и refout true, xorout 0x0000, check 0x4B37

Нашли ошибку?