Введение

Алгоритм Флетчера — это алгоритм вычисления контрольной суммы, зависящей от позиции, разработанный Джоном Г. Флетчером (1934–2012) в Лоуренс-Ливерморской лаборатории в конце 1970-х годов. Целью алгоритма Флетчера было обеспечение свойств обнаружения ошибок, приближающихся к свойствам циклического избыточного кода, но с меньшими вычислительными затратами, характерными для методов суммирования.

Пересмотр простых контрольных сумм

Как и в случае с более простыми алгоритмами контрольных сумм, контрольная сумма Флетчера предполагает разделение бинарных данных, подлежащих защите от ошибок, на короткие "блоки" битов и вычисление модульной суммы этих блоков. (Следует отметить, что терминология в этой области может быть запутанной. Все данные, подлежащие защите, именуются "словом", а части, на которые они разделены, – "блоками".) Например, данные могут представлять собой сообщение для передачи, состоящее из 136 символов, каждый из которых хранится как 8-битный байт, что в сумме составляет 1088 бит. Удобный размер блока составит 8 бит, хотя это не является обязательным. Аналогично, удобным модулем будет 255, но можно выбрать и другие значения. Таким образом, простая контрольная сумма вычисляется путем суммирования всех 8-битных байтов сообщения, деления на 255 и сохранения только остатка от деления. (На практике операция взятия модуля выполняется в процессе суммирования для контроля размера результата.) Значение контрольной суммы передается вместе с сообщением, увеличивая его длину до 137 байтов, или 1096 бит. Получатель сообщения может пересчитать контрольную сумму и сравнить ее с полученным значением, чтобы определить, было ли сообщение изменено в процессе передачи.

Недостатки простых контрольных сумм

Первое слабое место простой контрольной суммы заключается в том, что она нечувствительна к порядку следования блоков (байтов) в слове данных (сообщении). Если порядок изменить, значение контрольной суммы останется прежним, и изменение не будет обнаружено. Второй недостаток состоит в том, что множество возможных значений контрольной суммы ограничено и равно выбранному модулю. В нашем примере существует всего 255 возможных значений контрольной суммы, поэтому легко понять, что даже случайные данные имеют примерно 0,4% вероятность совпадения контрольной суммы с контрольной суммой нашего сообщения.

Контрольная сумма Флетчера

Флетчер устраняет обе эти слабости, вычисляя второе значение в дополнение к простой контрольной сумме. Это модульная сумма значений, которые принимает простая контрольная сумма при добавлении к ней каждого блока слова данных. Используется тот же модуль. Таким образом, для каждого блока слова данных, обрабатываемого последовательно, значение блока добавляется к первой сумме, а новое значение первой суммы затем добавляется ко второй сумме. Обе суммы начинаются с нуля (или другого известного значения). В конце слова данных применяется операция взятия остатка от деления, и два значения объединяются для формирования значения контрольной суммы Флетчера. Чувствительность к порядку блоков достигается тем, что после добавления блока к первой сумме он затем многократно добавляется ко второй сумме вместе с каждым последующим блоком. Например, если два соседних блока поменяются местами, блок, который изначально был первым, будет добавлен ко второй сумме на один раз меньше, а блок, который изначально был вторым, – на один раз больше. Конечное значение первой суммы останется прежним, но вторая сумма изменится, что позволит обнаружить изменение в сообщении. Множество возможных значений контрольной суммы теперь является квадратом множества значений для простой контрольной суммы. В нашем примере две суммы, каждая из которых может принимать 255 значений, дают 65025 возможных значений для объединенной контрольной суммы.

Обзор различных параметров алгоритма

Хотя существует бесконечное число параметров, в оригинальной работе рассматривается только случай K=8 (длина слова) с модулем 255 и 256. 16- и 32-битные версии (Fletcher 32 и 64) были выведены из исходного случая и исследованы в последующих спецификациях или статьях.

Флетчер-16

Когда слово данных разделяется на 8-битные блоки, как в приведенном выше примере, в результате получаются две 8-битные суммы, которые объединяются в 16-битную контрольную сумму Флетчера. Обычно вторая сумма умножается на 256 и добавляется к первой (простой) контрольной сумме, эффективно располагая суммы рядом друг с другом в 16-битном слове, при этом простая контрольная сумма находится в младшем разряде. Этот алгоритм называется контрольной суммой Флетчера-16. Также обычно подразумевается использование модуля 2⁸−1=255.

Флетчер-32

Когда слово данных разбивается на 16-битные блоки, в результате получаются две 16-битные суммы, которые объединяются в 32-битную контрольную сумму Флетчера. Как правило, вторая сумма умножается на 2¹⁶ и добавляется к первой (простой) контрольной сумме, эффективно располагая суммы рядом друг с другом в 32-битном слове, при этом простая контрольная сумма находится в младшем разряде. Этот алгоритм называется контрольной суммой Флетчера-32. Также обычно подразумевается использование модуля 2¹⁶-1 = 65535. Обоснование этого выбора такое же, как и для Fletcher-16.

Флетчер-64

Когда слово данных разбивается на 32-битные блоки, в результате получаются две 32-битные суммы, которые объединяются в 64-битную контрольную сумму Флетчера. Обычно вторая сумма умножается на 2<sup>32</sup> и добавляется к первой (простой) контрольной сумме, эффективно располагая суммы рядом друг с другом в 64-битном слове, при этом простая контрольная сумма находится в младшем разряде. Этот алгоритм называется контрольной суммой Флетчера-64. Также обычно подразумевается использование модуля 2<sup>32</sup>-1 = 4 294 967 295. Обоснование этого выбора такое же, как и для Fletcher-16 и Fletcher-32.

Сравнение с контрольной суммой Адлера

Контрольная сумма Адлера 32 является специализацией контрольной суммы Флетчера 32, разработанной Марком Адлером. Выбранный модуль (для обеих сумм) – простое число 65 521 (число 65 535 делится на 3, 5, 17 и 257). Первая сумма также инициализируется значением 1. Выбор простого модуля обеспечивает улучшенное "перемешивание" (ошибочные последовательности обнаруживаются с более равномерной вероятностью, что повышает вероятность обнаружения наименее заметных последовательностей, что обычно оказывает наибольшее влияние на общую производительность). Однако уменьшение количества возможных значений контрольной суммы несколько снижает производительность, компенсируя это преимущество. Одно исследование показало, что контрольная сумма Флетчера 32 превосходит контрольную сумму Адлера 32 как по производительности, так и по способности обнаруживать ошибки. Поскольку операция сложения по модулю 65 535 значительно проще и быстрее в реализации, чем операция сложения по модулю 65 521, контрольная сумма Флетчера 32 обычно является более быстрым алгоритмом.

Осторожность при модуле

Для Fletcher 16 выше и в приведенных ниже примерах используется модуль 255, однако в некоторых реальных реализациях используется модуль 256. Альтернативная контрольная сумма протокола TCP использует Fletcher 16 с модулем 256, как и контрольные суммы сообщений UBX * от GPS-приемников u-blox. Выбор используемого модуля зависит от конкретной реализации.

Слабые стороны

Контрольная сумма Флетчера не может различать блоки, состоящие только из нулей, и блоки, состоящие только из единиц. Например, если 16-битный блок в слове данных изменяется с 0x0000 на 0xFFFF, контрольная сумма Флетчера 32 останется прежней. Это также означает, что последовательность, состоящая только из байтов 00, будет иметь ту же контрольную сумму, что и последовательность (того же размера), состоящая только из байтов FF.

Реализация

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

Порядок битов и байтов (порядка эндианности / сети)

Как и в случае любого вычисления, которое разбивает двоичное слово данных на короткие блоки и рассматривает эти блоки как числа, любые две системы, ожидающие получить одинаковый результат, должны сохранять порядок битов в слове данных. В этом отношении контрольная сумма Флетчера ничем не отличается от других контрольных сумм и алгоритмов CRC и не требует дополнительных пояснений. Легко представить проблему порядка следования байтов, возникающую при передаче слова данных побайтово между системой с прямой (big-endian) и обратной (little-endian) порядком байтов, и последующем вычислении контрольной суммы Флетчера 32. Если блоки извлекаются из слова данных в памяти простым чтением 16-битового беззнакового целого числа, то значения блоков будут различаться в обеих системах из-за изменения порядка байтов 16-битных элементов данных в памяти, что, в свою очередь, приведет к разному результату контрольной суммы. Примеры реализации, приведенные выше, не рассматривают вопросы порядка следования байтов, чтобы не усложнять понимание алгоритма контрольной суммы. Поскольку контрольная сумма Флетчера 16 использует 8-битные блоки, она не подвержена влиянию порядка следования байтов.