Совпадение контрольной суммы (хеша) подтверждает только одно: битовая последовательность файла совпадает с эталоном на момент вычисления. Это полезно для обнаружения случайных ошибок передачи или повреждений диска. Но для безопасности — защиты от подмены, вредоносного кода или несанкционированных изменений — совпадения хеша недостаточно. В статье разбираем, почему это так, какие атаки это позволяют, и какие механизмы реально защищают целостность и подлинность.
- Что на самом деле проверяет хеш-функция
- Коллизии: когда два разных файла дают один хеш
- Парадокс дней рождения и сложность поиска
- Chosen-prefix collisions — реальная угроза
- Пример сценария
- Атаки преобраза: когда хеш известен, ищется исходник
- Атака расширения длины (Length Extension Attack)
- Supply chain: когда «оригинальный» файл уже вредоносен
- Что помогает против supply chain атак
- Подмена эталонного хеша: доверяй, но проверяй источник
- Что на практике обеспечивает безопасность файла
- Иерархия гарантий (от слабого к сильному)
- Практический чек-лист верификации релиза
- Типичные ошибки и заблуждения
- Сценарии: что делать в конкретных ситуациях
- Инструменты для практической работы
- Ограничения: чего ни хеш, ни подпись не гарантируют
- Резюме: следующий шаг
Что на самом деле проверяет хеш-функция
Хеш-функция — это детерминированный алгоритм, преобразующий данные произвольной длины в фиксированную строку битов. Главные свойства, которые ожидаются от криптографической хеш-функции:
- Однонаправленность — по хешу нельзя восстановить исходные данные.
- Стойкость к поиску преобраза — дан хеш h, найти любое сообщение m такое, что hash(m) = h, вычислительно нереально.
- Стойкость к коллизиям — найти две различные сообщения m1 ≠ m2 с одинаковым хешем вычислительно нереально.
Если файл скачан, и его SHA-256 совпадает с опубликованным разработчиком — вы знаете, что биты не изменились в пути. Но вы не знаете:
- Был ли исходный файл вредоносным изначально (компрометация сборки, supply chain).
- Не найдена ли коллизия, позволяющая подсунуть другой файл с тем же хешем.
- Не использует ли алгоритм уязвимый к атакам преобраза или расширения длины.
- Не подменён ли сам эталонный хеш на сайте или в репозитории.
Коллизии: когда два разных файла дают один хеш
Парадокс дней рождения и сложность поиска
Для хеша длины n бит идеальная стойкость к коллизиям составляет 2^(n/2) операций (атака по дням рождения). Для SHA-256 это 2^128 — астрономически много. Но для устаревших алгоритмов реальность иная:
| Алгоритм | Длина хеша | Теоретическая стойкость к коллизиям | Статус на 2024 год |
|---|---|---|---|
| MD5 | 128 бит | 2^64 | Полностью сломан: коллизии находятся за секунды на обычном CPU |
| SHA-1 | 160 бит | 2^80 | Практическая коллизия демонстрирована (SHAttered, 2017); chosen-prefix коллизии — 2019 |
| SHA-256 | 256 бит | 2^128 | Коллизий не найдено, считается стойким |
| SHA-3 / BLAKE2/3 | 256+ бит | 2^128+ | Стойкие, нет известных атак |
Chosen-prefix collisions — реальная угроза
Обычная коллизия находит любые два сообщения с одинаковым хешем. Chosen-prefix collision позволяет злоумышленнику взять два заранее заданных префикса (например, заголовки двух разных исполняемых файлов) и дописать к каждому специально подобранные суффиксы так, что итоговые хеши совпадут.
Это означает: можно создать два разных PDF, два разных исполняемых файла или два разных контейнера Docker с идентичным SHA-1, при этом оба файла будут валидными и выполнять разный код. Атака на SHA-1 стоит порядка $45–100 тысяч на облачных GPU (цены 2020–2023 гг.) — доступно для мотивированного атакующего.
Пример сценария
Разработчик публикует релиз с SHA-1 хешем. Злоумышленник заранее готовит два варианта: легитимный и с бэкдором. Подбирает суффиксы для коллизии. Подменяет файл на зеркале или в репозитории. Пользователь проверяет SHA-1 — совпадает. Запускает заражённый бинарь.
Именно поэтому SHA-1 и MD5 запрещены для любых целей безопасности (подписание кода, сертификаты TLS, верификация релизов). Они допустимы только для некритичных проверок целостности при передаче данных, где угроза намеренной подмены исключена.
Атаки преобраза: когда хеш известен, ищется исходник
Первая преобразная (preimage): дан хеш h, найти m такое, что hash(m) = h. Вторая преобразная: дан m1, найти m2 ≠ m1 с тем же хешем.
Для стойких хешей (SHA-256, SHA-3, BLAKE2) лучшие известные атаки требуют ~2^n операций — нереально. Но для слабых алгоритмов или нестандартного использования (например, hash(secret || message) без HMAC) существуют атаки расширения длины.
Атака расширения длины (Length Extension Attack)
Меркле-Дамгård конструкция (MD5, SHA-1, SHA-256, SHA-512) позволяет: зная hash(m) и длину m, вычислить hash(m || padding || m’) для произвольного m’ — не зная m.
Это ломает схемы вида token = hash(secret || data) как MAC. Атакующий может дописать данные и вычислить валидный токен без знания секрета. Защита — использовать HMAC (HMAC-SHA256(key, data)) или хеши на базе स्पонджа (SHA-3, BLAKE2/3), устойчивые к расширению длины.
Supply chain: когда «оригинальный» файл уже вредоносен
Самый частый вектор компрометации в 2020–2024 гг. — не коллизии хешей, а подмена на этапе сборки или распространения:
- Компрометация CI/CD (SolarWinds, CodeCov, 3CX).
- Вредоносные зависимости в npm/PyPI/RubyGems (typosquatting, dependency confusion).
- Подмена артефактов в репозитории (GitHub Actions, Docker Hub).
- Скомпрометированные ключи подписи разработчика.
В этих случаях хеш совпадает с опубликованным, потому что публикуемый артефакт уже содержит вредоносный код. Проверка хеша ничего не обнаружит.
Что помогает против supply chain атак
- Воспроизводимые сборки (reproducible builds) — несколько независимых сторон собирают из исходников идентичные бинарники. Если хеш совпадает у всех — вероятность подмены в сборке снижается.
- Подписание артефактов — криптографическая подпись (Ed25519, RSA-PSS, ECDSA) приватным ключом разработчика. Проверка подписи подтверждает: файл создан владельцем ключа и не изменён.
- Transparency logs / Sigstore / Rekor — публичный журнал подписей, позволяющий аудировать историю релизов.
- SBOM (Software Bill of Materials) — список зависимостей с версиями и хешами для аудита.
- Политика pinning зависимостей — фиксация точных версий и хешей в lock-файлах.
Подмена эталонного хеша: доверяй, но проверяй источник
Если атакующий получил доступ к сайту проекта, репозиторию релизов или DNS — он может заменить и файл, и опубликованный хеш. Пользователь скачает оба, проверит — совпадут. Примеры:
- Компрометация веб-сервера (Linux Mint 2016, PHP 2021).
- DNS-спуфинг / BGP-хайджек репозитория.
- Атака на аккаунт мейнтейнера в GitHub / PyPI / npm.
Защита — многофакторная верификация источника:
- Сравнение хеша из нескольких независимых источников (сайт, GitHub Releases, зеркала, mailing list).
- Проверка криптографической подписи (GPG, Minisign, cosign) — ключ разработчика сложнее скомпрометировать, чем веб-страницу.
- Использование transparency logs (Sigstore, Go checksum database).
- Проверка TLS-сертификата и Certificate Transparency логов при скачивании по HTTPS.
Что на практике обеспечивает безопасность файла
Иерархия гарантий (от слабого к сильному)
- CRC32 / Adler-32 — только случайные ошибки передачи. Никакой безопасности.
- MD5 / SHA-1 — случайные ошибки + устойчивость к нецелевым повреждениям. Коллизии тривиальны — не для безопасности.
- SHA-256 / SHA-512 / BLAKE2b / BLAKE3 — стойкость к коллизиям и преобразам. Хорошо для проверки целостности при доверенном источнике.
- HMAC-SHA256 / KMAC / BLAKE2 с ключом — целостность + подлинность (требует общего секрета).
- Цифровая подпись (Ed25519, RSA-PSS, ECDSA-P256) + PKI / Web of Trust / Sigstore — целостность + подлинность + неотрекаемость + публичная верифицируемость. Золотой стандарт для релизов ПО.
- Воспроизводимая сборка + подпись + transparency log — максимальный уровень доверия к бинарнику.
Практический чек-лист верификации релиза
- Получите файл с официального источника (HTTPS, проверенный домен).
- Проверьте TLS-сертификат (домен, срок, CA, CT-логи).
- Скачайте файл подписи (.sig, .asc, .minisig) и публичный ключ разработчика из независимого источника (keyserver, страница проекта в GitHub, Keybase, DNS-OPENPGPKEY).
- Проверьте подпись: gpg —verify file.sig file или minisign -Vm file -P pubkey.
- При необходимости — сверьте SHA-256/BLAKE2b с опубликованным значением как дополнительную проверку.
- Для критических компонентов — проверьте воспроизводимую сборку или наличие записи в transparency log (Rekor, Go checksum db).
Типичные ошибки и заблуждения
- «SHA-256 совпал — значит файл чистый» — нет, значит только битово идентичен тому, что хешировался. Источник мог быть скомпрометирован.
- «MD5 достаточно для проверки скачанного образа» — нет, атакующий может подготовить коллизию заранее. Используйте SHA-256 или BLAKE2b.
- «Хеш в имени файла (filename.sha256) — это защита» — нет, это удобство. Файл с хешем можно подменить вместе с образом.
- «Проверяю хеш, который лежит рядом с файлом на том же сервере» — циклическая проверка. Нужен независимый источник хеша или подпись.
- «GPG сложен, лучше проверить SHA-256» — GPG/Minisign/cosign сложнее в первый раз, но дают гарантию подлинности, которой нет у голого хеша. Minisign и cosign — простые современные альтернативы.
- «Подпись есть, но я не проверяю отпечаток ключа» — если не верифицируете fingerprint ключа через сторонний канал, доверяете первому попавшемуся ключу (TOFU — trust on first use).
Сценарии: что делать в конкретных ситуациях
| Ситуация | Минимум проверок | Рекомендуемый уровень |
|---|---|---|
| Скачивание образа ОС / прошивки роутера | SHA-256 с официального HTTPS-сайта | GPG/Minisign подпись + сверка fingerprint ключа через второй канал |
| Установка пакета из системного репозитория (apt, dnf, pacman) | Автоматическая проверка подписи репозитория менеджером пакетов | Включена по умолчанию; не отключайте проверку подписей |
| pip install / npm install / cargo add | Hash pinning в lock-файле | Включение требования подписей (npm —require-scripts, pip —require-hashes), использование sigstore/cosign для контейнеров |
| Запуск бинарника из GitHub Releases | Сравнение SHA-256 с релизом | Проверка cosign/Minisign подписи мейнтейнера + reproducible build (если есть) |
| Обмен файлами внутри команды | SHA-256 в защищённом чате | HMAC с общим секретом или подпись Ed25519 |
| Верификация бэкапа / архива | SHA-256 / BLAKE3 при создании | Подпись архива ключом архивиста + периодическая перепроверка |
Инструменты для практической работы
- sha256sum / sha512sum / b2sum / b3sum — быстрый расчёт хешей (coreutils, b2sum из b2-tools, b3sum из b3sum пакета).
- Minisign — простое подписание/верификация Ed25519, короткие ключи, нет ключевых серверов, подходит для релизов.
- cosign / Sigstore — keyless подписание через OIDC, transparency log Rekor, интеграция с контейнерами и бинарниками.
- GPG / GnuPG — классика, Web of Trust, поддержка везде, но сложнее в использовании.
- age / rage — современное симметричное/асимметричное шифрование, можно использовать для зашифрованных подписей.
- reprotest / diffoscope — проверка воспроизводимости сборок.
- in-toto / SLSA — фреймворки для защиты supply chain от исходников до артефакта.
Ограничения: чего ни хеш, ни подпись не гарантируют
Даже идеальная криптография не защитит от:
- Уязвимостей в самом коде (баги, логические ошибки, zero-day).
- Злонамеренного кода, легально добавленного разработчиком (backdoor by design).
- Компрометации среды выполнения (заражённое ОС, гипервизор, hardware implants).
- Социальной инженерии (пользователь сам запускает вредонос, игнорируя предупреждения).
- Атак на цепочку доверия ключей (скомпрометированный CA, подмена ключа в keyserver без проверки fingerprint).
Хеш и подпись — это инструменты верификации происхождения и целостности. Они отвечают на вопрос «этот файл именно тот, что выпустил автор?». На вопрос «безопасен ли этот код?» они ответить не могут — нужен аудит кода, SAST/DAST, песочницы, мониторинг поведения.
Резюме: следующий шаг
Главный принцип: хеш — для целостности, подпись — для подлинности, воспроизводимая сборка + transparency log — для доверия к процессу.
Если вы сегодня проверяете только SHA-256 из того же источника, что и файл — начните с двух действий:
- Найдите и импортируйте публичный ключ подписи разработчика (GPG/Minisign/cosign) из независимого источника.
- Настройте автоматическую проверку подписей для ваших основных каналов получения ПО (пакетный менеджер, CI/CD, container runtime).
Для критических систем добавьте требование воспроизводимых сборок и проверку записей в transparency logs. И помните: совпадение хеша — это начало проверки, а не её конец.
Материал носит информационный характер и не заменяет профессиональную оценку безопасности в конкретной инфраструктуре. При защите критических систем обратитесь к специалисту по информационной безопасности для аудита цепочки поставок и модели угроз.
