Как выполнить CHECKSUM для целостности данных (BYTE ORDER) - PullRequest
2 голосов
/ 12 марта 2019

Некоторое время назад мне потребовалась функция для выполнения контрольной суммы для проверки целостности данных при обмене дейтаграммами через Интернет.В те дни я нашел эту функцию, просто скопировал / вставил и использовал ее.

Checksum (void* buf, int bufsize) {
    register int            sum    = 0;
             word           answer = 0;
    register word           *w     = (word*) buf;
    register int            nleft  = bufsize;

    while (nleft > 1) {
        sum += *w++;
        nleft -= 2;
    }

    if (nleft == 1) {
        *(byte*)(&answer) = *(byte*)w;
        sum += answer;
    }

    sum = (sum>>16) + (sum&0xFFFF);
    sum += (sum>>16);
    answer = ~sum;
    return answer;
}

Сегодня я работаю над другой программой, которая требует контрольной суммы для обеспечения целостности данных, но на этот раз я хотела посмотреть, как она работает иесть одно сомнение.

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

Мои конкретные вопросы:

  1. Ожидаются ли слова из буфера в младшем или старшем порядке?Интуиция подсказывает мне, что байты слова должны быть в BIG ENDIAN (по соглашению), поэтому контрольная сумма одинакова для любой машины, но этот алгоритм просто суммирует значения (на платформе x86 - little-endian), что если другая сторонабольшая порядковая платформа?Будет ли это работать, если я суммирую значения байтов, инвертированные для младшего и прямого байтов?

  2. Если размер буфера нечетный, последний байт добавляется непосредственно к сумме, нодобавляется ли оно просто как значение ИЛИ как байт НИЗКОГО ЗАКАЗА слова (учитывая, что следующий байт равен 0 - байт ВЫСОКОГО ЗАКАЗА в младшем порядке)?

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

Ответы [ 2 ]

0 голосов
/ 12 марта 2019
  1. Ожидаются ли слова из буфера в младшем или старшем порядке?

Для работы в сети («полезная нагрузка» любого пакета, отправленного или полученного черезсеть, использующая любой протокол); буфер всегда содержит октеты (байты) , и октеты всегда поступают в том же порядке, в котором они были отправлены (проблема «порядка байтов» отсутствует).

Перед тем, как программное обеспечение использует сетевую передачу для отправкиданные по сети преобразуют что-то (например, структуру на языке высокого уровня) в буфер октетов.Это называется «сериализацией» и необходимо, чтобы избежать всех видов катастроф переносимости (не только «endianess», но и таких вещей, как заполнение структуры компилятора / реализации, различия в формате с плавающей запятой, различия в наборе символов и т. Д.).

После того, как программное обеспечение получает данные из сети, оно преобразует буфер октетов во что-то (например, структуру на языке высокого уровня).Это называется «десериализация».Он включает в себя 3 цели:

  • проверка работоспособности (попытка убедиться, что вы получили то, что, по вашему мнению, вы должны были получить)
  • авторизация (попытка убедиться в правильности отправителя ине злоумышленник)
  • преобразование буфера октетов обратно во что-то (например, структуру на языке высокого уровня).

Ни одна из этих вещей (сериализация и деСериализация) являются частью самой сети - они «до сети» и «после сети», а не «в середине сети».

Обратите внимание, что (исходя из ваших вопросов) вы предположили, чтобуфер является структурой высокого уровня и не смог сериализовать / десериализовать;таким образом, ваш код (включая контрольную сумму) будет поврежден и потерпит неудачу (и, вероятно, не только из-за "endianess").

Если размер буфера нечетный, последний байт добавляется непосредственно к сумме, но добавляется ли он просто как значение ИЛИ как байт НИЗКОГО ЗАКАЗА слова (учитывая, что следующий байт равен 0 - байт ВЫСОКОГО ЗАКАЗА вlittle endian)?

Да.

Обратите внимание, что основная часть вычисления контрольной суммы (которая неверно предполагает, что «буфер октетов» является словами) сломается из-за«endianess» (если у отправителя и получателя разные порядковые номера, проверка контрольной суммы «will» (см. примечание) завершится неудачей для всех сообщений, длина которых превышает 1 октет).Простой способ избежать этого - использовать «сумму байтов» (вместо «сумма слов»).Лучшим способом избежать этого является более сложная контрольная сумма (например, CRC-32, которая используется TCP).

Примечание: при использовании 16-битной контрольной суммы в 65536 есть как минимум 1 вероятность того, чтоконтрольная сумма пройдет случайно благодаря одной лишь удаче;и подход «сумма чего-либо» подвержен различным сбоям (например, если отправитель или получатель неправильно указали размер сообщения и на конце имеется множество нулей, которых не должно быть, тогда «неправильные нули» не будут действоватьконтрольная сумма).Это означает, что когда отправитель и получатель используют один и тот же порядок байтов, есть вероятность «хуже, чем 1 в 65536», что контрольная сумма пройдет, когда она не должна;и это также означает, что когда отправитель и получатель используют разные порядковые номера, а размер сообщения превышает 1 октет, существует вероятность того, что контрольная сумма пройдет, когда она «должна», «лучше, чем 1 в 65536».

0 голосов
/ 12 марта 2019

Ожидаются ли слова из буфера в младшем или старшем порядке?

Вы не можете знать без определенного протокола.Порядковый номер протокола иногда называют «порядковым номером сети».Традиционно большинство протоколов используют порядковый номер с прямым порядком байтов, но это не гарантируется.

Если размер буфера нечетный, последний байт добавляется непосредственно к сумме, но добавляется ли он как значение ИЛИ какбайт НИЗКОГО ЗАКАЗА слова (учитывая, что следующий байт равен 0 - байт ВЫСОКОГО ЗАКАЗА с прямым порядком байтов)?

Не имеет большого значения, это будет плохо для обнаружения ошибок в любом случае - этопотерпит неудачу для большинства двухбитных ошибок.Я настоятельно рекомендую использовать вместо него CRC: один из стандартных CRC-16 или CRC-32 в зависимости от размера данных.

...