Контрольная сумма: что это и почему это важно
Сегодня в вашем лексиконе появится важная новая фраза: контрольная сумма. Это инструмент опытных разработчиков, админов и хакеров, и сегодня он станет вашим.
Представьте ситуацию: вы приходите в магазин за наушниками. Находите нужные на витрине, пробуете их, вам всё нравится. Вы просите продавца принести такие же со склада, в упаковке.
Продавец приносит коробку, и вы понимаете, что вас хотят обмануть. Упаковку явно до этого вскрывали, в комплекте не все провода и накладки, плёночки сняты. Этими наушниками явно пользовались до вас.
Сотрудник говорит, что это ошибка в списке комплектности, а товар на самом деле новый, просто такой пришёл с завода. Вы ему не верите, отказываетесь от покупки и идёте в другой магазин. Там вы находите такие же наушники, проверяете и радуетесь, что купили нужную вещь.
В мире информации происходит почти то же самое: товар на складе — это какие-то данные, а список комплектности товара — это контрольная сумма, которая показывает, изменялись эти данные или нет. Если понимать, что это такое и как этим пользоваться, можно проверить подлинность файла и обезопасить себя от подделок, вирусов и шпионов.
Как это работает
На самом деле именно контрольной суммы уже нет — это название нам досталось с тех времён, когда для проверки точности передачи данных использовали 7 бит вместо 8. Восьмой бит был контрольным, и в нём находилась сумма первых семи бит без учёта старших разрядов. Когда получателю приходила очередная порция данных, он складывал 7 бит и сравнивал сумму с восьмым. Если они совпадали, значит, данные, скорее всего, передались верно. Тогда линии связи были не такими надёжными, как сейчас, и если что-то передавалось неправильно, такие данные нужно было отправить заново. С тех пор и пошло понятие контрольной суммы.
Сейчас сумму уже никто не использует, а вместо этого работают специальные программы:
- Берут данные, для которых нужно составить контрольную сумму.
- По специальному алгоритму эти данные превращаются в одну строку из символов.
- Эту строку текста прикладывают к исходному файлу и говорят — ребята, вот контрольная сумма (то есть строка). Если вы не уверены, что всё скачали правильно, проверьте.
- Те, кто скачал исходный файл, запускают программу проверки контрольных сумм и говорят ей — вот файл, а вот его контрольная сумма, проверь, пожалуйста, всё ли тут правильно.
- Программа сама составляет контрольную сумму по тому же алгоритму и сравнивает с вашей.
- Если контрольные суммы совпадают — всё отлично, данные в порядке, можно пользоваться. Если нет — программа выведет сообщение, что суммы отличаются. Это значит, что во время скачивания возникла ошибка или кто-то специально подменил исходные данные, чтобы навредить вам.
Смысл технологии в том, что для любого файла и алгоритма есть только одна контрольная сумма. Если в файле изменить предложение, слово или несколько символов, контрольная сумма будет уже другой. Это как цифровой отпечаток пальца, только для данных.
Самый простой вариант организовать контрольную сумму — использовать хеши, например, MD5. Мы уже говорили про хеши в статье про Фейсбук и утерянные пароли, но MD5 — многогранная вещь, и в своё время его все использовали для создания контрольных сумм.
Но примерно с 2006 года все стали переходить на другие алгоритмы (CRC32, SHA-1, SHA-2 или MD5crypt). Дело в том, что уже есть методы, которые за приемлемое время могут взломать MD5-хеш и сделать другой файл с тем же размером и почти таким же содержимым, что и ваш. Это значит, что злоумышленник может подделать данные таким образом, что проверка контрольной суммы пройдёт успешно и вы будете думать, что всё в порядке.
Почему это важно
Если вы знаете контрольную сумму и алгоритм её нахождения, вы всегда можете проверить файл на целостность — скачался ли файл целиком и вообще тот ли это файл, что нужно.
Например, вы качаете новую прошивку на свой телефон. Если файл скачается неправильно, не до конца или с ошибками, во время перепрошивки телефон может сломаться, и восстановить его будет уже нельзя. Чтобы такого не было, производители прошивок прикладывают к файлам контрольную сумму, чтобы каждый мог проверить перед перепрошивкой, в порядке ли сам файл.
Чаще всего контрольную сумму используют разработчики ПО, которые выкладывают на своих страницах официальный софт и драйвера. Они говорят: ребята, вот файл, а вот его контрольная сумма. Если качаете у нас — проверьте, без ошибок ли вы скачали. А если качаете не у нас — сравните их контрольную сумму с нашей, вдруг они вам под видом драйвера хотят подсунуть какой-то вирус.
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Для чего применяют чексуммы программирование
pg_checksums — включить, отключить или проверить контрольные суммы данных в кластере Postgres Pro
Синтаксис
pg_checksums [ параметр . ] [[ -D | —pgdata ] каталог_данных ]
Описание
Утилита pg_checksums позволяет проверить, включить или отключить контрольные суммы данных в кластере Postgres Pro . Перед запуском pg_checksums сервер должен быть остановлен в штатном режиме. При проверке контрольных сумм она возвращает нулевой код состояния, если ошибок не найдено, либо ненулевой код, если обнаружится хотя бы одна ошибка. При включении или отключении контрольных сумм ненулевой код завершения показывает, что выполнить операцию не удалось.
В процессе проверки контрольных сумм проверяется каждый файл в кластере. При включении контрольных сумм каждый файл в кластере перезаписывается на месте, а при отключении изменяется только файл pg_control .
Параметры
Принимаются следующие параметры командной строки:
-D каталог
—pgdata= каталог
Указывает каталог, в котором располагается кластер баз данных. -c
—check
Запускает проверку контрольных сумм. Это режим по умолчанию, который выбирается, когда не указан никакой другой. -d
—disable
Отключает контрольные суммы. -e
—enable
Включает контрольные суммы. -f файловый_узел
—filenode= файловый_узел
Проверять контрольные суммы только в отношении, которому соответствует указанный файловый_узел . -N
—no-sync
По умолчанию pg_checksums ждёт, пока все файлы не будут надёжно записаны на диск. С данным параметром pg_checksums завершается быстрее, без ожидания, но в случае неожиданного сбоя операционной системы каталог с изменёнными файлами может повредиться. Этот параметр может быть полезен при тестировании; в производственной среде применять его не следует. В режиме —check он не оказывает никакого влияния. -P
—progress
Включает вывод сообщений о прогрессе. Эти сообщения будут выводиться при проверке или включении контрольных сумм. -v
—verbose
Выводить подробные сообщения, в частности список всех проверенных файлов. -V
—version
Выводит версию pg_checksums и завершает работу. -?
—help
Показывает справку по аргументам командной строки pg_checksums и завершает работу.
Переменные окружения
Указывает каталог, в котором располагается кластер баз данных; может переопределяться параметром -D . PG_COLOR
Выбирает вариант использования цвета в диагностических сообщениях. Возможные значения: always (всегда), auto (автоматически) и never (никогда).
Замечания
Включение контрольных сумм в большом кластере может занять продолжительное время. Пока эта операция не закончится, нельзя запускать сервер или другие программы, которые могут произвести запись в каталог данных, иначе возможна потеря данных.
В конфигурациях, где организована репликация, и она осуществляется путём непосредственного копирования блоков отношений на уровне файлов (например, с помощью pg_rewind ), включение или отключение контрольных сумм может привести к повреждению страниц (а именно, расхождению контрольных сумм), если эта операция не будет выполнена согласованно на всех узлах. Поэтому в подобных конфигурациях рекомендуется остановить все кластеры, с тем чтобы одновременно переключить их в другой режим. Ещё один безопасный вариант — ликвидировать все ведомые серверы, произвести нужную операцию на ведущем, а затем создать ведомые серверы заново.
Если pg_checksums прерывается или работающий процесс уничтожается при включении или отключении контрольных сумм, конфигурация контрольных сумм в кластере остаётся неизменной, и pg_checksums можно перезапустить ещё раз для повторения невыполненной операции.
| Пред. | Наверх | След. |
| pg_archivecleanup | Начало | pg_controldata |
qhb_checksums
qhb_checksums — утилита для проверки, включения и выключения контрольных сумм данных в кластере QHB. Сервер должен быть штатным образом выключен перед запуском qhb_checksums . При проверке контрольных сумм код завершения равен нулю, если ошибок нет, и ненулевой, если обнаружена хотя бы одна ошибка контрольной суммы. При включении или отключении контрольных сумм ненулевой код завершения, означает, что операция не удалась.
У всех файлов таблиц есть заголовок, по умолчанию поле с контрольной суммой в нём равно 0, также в общем файле ControlFile «версия чексумм» = 0 (1 — включена). При первом запуске нужно включить эти чексуммы с помощью флага —enable, который поставит версию чексумм «1» и изменит поле чексуммы во всех заголовках файлов таблиц БД (папки global, base, pg_tblspc). Если нужно проверить, правильные ли чексуммы в файлах, то программа запоминает значение чексуммы из файла, обнуляет его, считает новое, сравнивает и возвращает на место старое значение (если оно не совпало с подсчитанным — выводится ошибка с указанием места происшествия). Если чексуммы надо выключить — программа меняет значение версии чексумм на 0 и ничего не делает с файлами таблиц
При проверке контрольных сумм сканируется каждый файл в кластере.При включении контрольных сумм каждый файл в кластере перезаписывается. Отключение контрольных сумм обновляет только файл pg_control .
Параметры
- -f filenode
—filenode= filenode Проверить контрольнные суммы только для отношения с указанным filenode - -D directory
—pgdata= directory Указывает каталог, в котором хранится кластер базы данных. (env: PGDATA=/tmp/qhb-data/)
Доступны следующие параметры командной строки:
Флаги (FLAGS)
- -c
—check Проверяет контрольные суммы. Это режим по умолчанию, если ничего не указано. - -d
—disable
Отключить контрольные суммы. - -e
—enable
Включить контрольные суммы. - -h
—help Вывести справочную информацию. - -N
—no-sync Не ждать, пока изменения будут безопасно записаны на диск. По умолчанию qhb_checksums будет ожидать безопасной записи всех файлов на диск. Этот параметр позволяет qhb_checksums завершаться без ожидания, что быстрее, но в случае сбоя операционной системы может привести к повреждению обновленного каталога данных. Как правило, этот параметр полезен для тестирования, но его не следует использовать в продакшене. - -P
—progress Выводить сообщения о прогрессе выполнения. Сообщения будут выводиться при проверке или включении контрольных сумм. - -V
—version Показать информацию о версии и выйти - -v
—verbose Выводить подробные сообщения. Уровень отладки по умолчанию: Warn
Окружение
- Указывает каталог, в котором хранится кластер базы данных; может быть переопределено с помощью параметра -D .
- Указывает, использовать ли цвета в диагностических сообщениях. Возможные значения always, auto, never .
Примечания
Включение контрольных сумм в большом кластере может занять много времени. Во время этой операции кластер или другие программы, выполняющие запись в каталог данных, не должны запускаться, иначе может произойти потеря данных.
При использовании репликации, которая выполняется путем неспосредственного копирования блоков отношений на уровне файлов отношений (например, qhb_rewind), включение или отключение контрольных сумм может привести к повреждению страниц в виде расхождения контрольных сумм, если эта операция не будет выполнена согласованно на всех узлах. Поэтому при включении или отключении контрольных сумм рекомендуется остановить все кластеры, для того чтобы переключить их в другой режим. Удаление всех ведомых серверов, выполнение операции на основном сервере и создание ведомых серверов заново, также является безопасным методом.
Если qhb_checksums прерывается или уничтожается при включении или отключении контрольных сумм, конфигурация контрольной суммы данных кластера остается неизменной, и qhb_checksums можно повторно запустить для выполнения той же операции.
Обработка ошибок
Ошибка Possibly encrypted block, проявляется либо при шифровке файла, либо при очень серьёзном повреждении файла, подразумевая под собой MismatchBlockChecksum .
Примеры
- qhb_checksums -e
первый запуск, включение контрольных сумм, в конце выводится статистика с количеством обработанных блоков и файлов, любая ошибка приводит к остановке и выходу с кодом 1. - qhb_checksums -с
проверка уже включённых контрольных сумм, отношение к статистике и ошибкам такое же, как у —enable - qhb_checksums -d
последний запуск программы, выключает контрольные суммы, несмотря на любые ошибки, кроме Permission denied на /global/pg_control
—enable , —check и —disable — три главных аргумента, к которым могут быть применены следующие флаги:
- —verbose для вывода отладочной информации
- —no-sync для отключения сброса изменений на диск
- —progress для отображения хода выполнения
Контрольная сумма UDP
Большинство проектов, над которыми я когда-либо работал, так или иначе не работают без передачи данных по сети. Последним проектом не выходящим за рамки одного компьютера была поддержка Wow64 в ядре Windows. Тем не менее возится с кодом, непосредственно обрабатывающим IP пакеты мне довелось всего пару раз. Оба раза я столкнулся с одной и той же ошибкой вычисления контрольных сумм в IP стеке. В одном случае, сетевая карта ошибочно помечала хорошие пакеты как испорченные. В другом — две библиотеки, написанные разными людьми, неверно вычисляли контрольную сумму некоторых пакетов. Одна из библиотек широко использовалась в “боевых” условиях. Немного удивительно, что ошибка оставалась незамеченной так долго.
Корнями этот баг уходит в 1980-й год, когда был опубликована спецификация протокола UDP. Чтобы разобраться в чем заключается ошибка, нужно сначала разобраться как работают контрольные суммы в IP стеке. В IPv4 пакете есть две контрольные суммы: контрольная сумма IPv4 заголовка и контрольная сумма протокола следующего уровня (UDP, TCP, ICMP, и т.п.). Контрольная сумма IPv4 заголовка защищает только IPv4 заголовок. Контрольная сумма протокола следующего уровня защищает тело пакета и некоторые поля из заголовка.
Контрольная сумма IPv4 заголовка вычисляется по такому алгоритму:
The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16 bit words in the header. For purposes of computing the checksum, the value of the checksum field is zero.
Поле контрольной суммы — 16 битное дополнение до единицы суммы всех 16 битных слов, вычисленной в обратном коде. Для целей вычисления контрольной суммы, значение поля контрольной суммы считается равным нулю.
В переводе с птичьего на человеческий это означает вот что. Обратный код — это способ представления чисел в двоичном коде. В отличие от более привычного дополнительного кода, обратный код использует два разных представления нуля: положительный и отрицательный ноль. Инвертирование числа дает то же самое число с обратным знаком:
0111 +7 0110 +6 0101 +5 0100 +4 0011 +3 0010 +2 0001 +1 0000 +0 # положительный ноль 1111 -0 # отрицательный ноль 1110 -1 1101 -2 1100 -3 1011 -4 1010 -5 1001 -6 1000 -7
Чтобы получить правильный результат при сложении двух чисел в обратном коде, перенос из старшего разряда просто прибавляется к сумме:
0110 +6 + 1101 -2 ------ 0011 +3 + 1 # перенос из старшего разряда ------ 0100 +4
“сумма всех 16 битных слов, вычисленной в обратном коде” — означает не что иное, как сумму всех 16 битных слов заголовка выполненную по вышеописанному правилу. “16 битное дополнение до единицы суммы” — указывает, что после вычисления суммы всех 16 битных слов заголовка, полученное значение инвертируется.
Такой алгоритм позволяет проверить пакет просто вычислив сумму всех 16 битных слов заголовка (включая поле контрольной суммы). Если результат равен нулю — пакет не поврежден. Что более важно, он позволяет легко обновить контрольную сумму, при изменении только некоторый полей заголовка, не вычисляя её заново. Это свойство было полезно при создании высокопроизводительных IP маршрутизаторов.
Написать и протестировать код, реализующий этот алгоритм, казалось бы можно за пол-часа, с перерывом на кофе. Однако эта простота обманчива. Существуют три RFC, поясняющие неочевидные детали инкрементального обновления контрольной суммы: RFC 1071, RFC 1141, RFC 1624. В каждом из этих документов были исправлены ошибки, найденные после их опубликования.
Как я уже упоминал выше, в каждом IPv4 пакете есть две контрольные суммы. Пока что мы обсудили только контрольную сумму заголовка IPv4 пакета. Вторая контрольная сумма (UDP или TCP) вычисляется по другому алгоритму.
Checksum is the 16-bit one’s complement of the one’s complement sum of a pseudo header of information from the IP header, the UDP header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets.
If the computed checksum is zero, it is transmitted as all ones (the equivalent in one’s complement arithmetic). An all zero transmitted checksum value means that the transmitter generated no checksum (for debugging or for higher level protocols that don’t care).
Контрольная сумма — 16 битное дополнение до единицы суммы псевдо заголовка, заполненного информацией из IP заголовка, UDP заголовка и данных, выровненных до границы двух байт.
Если вычисленная сумма равна нулю, она передается как все единицы ( эквивалентное значение в дополнительном коде). Нулевая контрольная сумма в пакете означает что передающая сторона не указала контрольную сумму (в целях отладки или при использовании протоколов более высокого уровня которым все равно).
На первый взгляд этот алгоритм сильно отличается от алгоритма вычисления контрольной суммы заголовка IPv4, но при внимательном рассмотрении оказывается, что оба алгоритма очень похожи. Первый абзац фактически описывает ту же самую инвертированную сумму 16-битных слов в обратном коде. Единственное отличие — это диапазон данных (псевдо заголовок, UDP заголовок и данные вместо IPv4 заголовка), которые покрываются контрольной суммой.
Настоящее отличие кроется во втором абзаце. Если его перефразировать, то он утверждает, что контрольная сумма UDP необязательна. Передающая сторона может просто передать ноль вместо вычисления контрольной суммы. В случае если вычисленная контрольная сумма получается равной нулю, то она передается как -0 , т.е. 0xffff. Фраза “эквивалентное значение в дополнительном коде” специально уточняет, что два разных значения в дополнительном коде ( +0 и -0 ) соответствуют нулю и такая замена разрешена.
Именно здесь и скрывается баг. Дело в том, что при сложении чисел в обратном коде единственный способ способ получить значение 0x0000 ( +0 ) — это сложить +0 и +0 . Любая другая комбинация чисел дает результат от 0x0001 ( +1 ) до 0xffff ( -0 ). Любой корректный IP пакет содержит ненулевые байты, что гарантирует, что сумма 16-битных полей корректного пакета не будет равна 0x0000 ( +0 ).
Итак сумма не может равняться +0 и 0x0000 используется как зарезервированное значение — пока что все сходится, разве нет? А вот и нет. Мы забыли, что вычисленная сумма инвертируется при передаче. Получается вот такой странный специальный случай:
# Сумма полей Контрольная Поле контрольной # пакета сумма суммы в пакете 0x0001 0xfffe 0xfffe 0x0002 0xfffd 0xfffd 0x0003 0xfffc 0xfffc . 0xfffd 0x0002 0x0002 0xfffe 0x0001 0x0001 0xffff 0x0000 0xffff
Получается, что спецификация подставляет подножку разработчикам и заставляет их на ровном месте добавлять в код обработку специального случая. Программисты с удовольствием наступают на эти грабли и пишут код, обрабатывающий этот случай неправильно. Я видел обе вариации этой ошибки. В одном случае контрольная сумма UDP пакета вычислялась по алгоритму для IPv4. В другом случае было ровно наоборот, - неправильно вычислялась контрольная сумма заголовка IP пакета. А ведь достаточно было бы взять другое зарезервированное значение для обозначения невычисленной контрольной суммы - 0xffff ( -0 ) и желаемое поведение получилось бы естественным образом безо всяких ухищрений.
Забавно, что одна из причин по которым это баг может оставаться незамеченным долгое время это то, что в большинстве случаем вычисление контрольных сумм переносится с центрального процессора на сетевую карту (checksum offloading). Соответственно ошибочный код просто не выполняется. Другая причина заключается в том, что эта ошибка в среднем затрагивает один пакет из 65535 (0.0015% пакетов).
В заключение добавлю, что алгоритма вычисления контрольной суммы один из немногих примеров “промышленного” кода. который тривиально поддается 100% проверке полным перебором. Там всего-навсего 65536 возможных значений.