Как система определяет настоящий тип файла: расширения, сигнатуры и MIME-типы

Когда вы дважды щёлкаете по файлу, система за доли секунды решает, чем его открыть. Кажется, что она «смотрит на расширение», но на деле всё сложнее: у файла есть как минимум три независимых признака типа — расширение в имени, MIME-тип, переданный вместе с файлом, и содержимое самого файла. Настоящий тип определяется в первую очередь по содержимому, а точнее по специальным байтам в его начале, которые называют сигнатурой или магическими числами. Расширение — лишь подсказка, которой система доверяет не всегда.

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

Три признака типа файла и их иерархия

У любого файла можно выделить три слоя информации о его типе:

  • Расширение имени — суффикс после точки: .jpg, .pdf, .exe. Его легко изменить, оно ничего не говорит о содержимом и существует в основном для удобства человека и как подсказка для ОС.
  • MIME-тип — метка вида image/jpeg или application/pdf, которая передаётся вместе с файлом: в HTTP-заголовке Content-Type при скачивании, в письме или в метаданных. Её выставляет отправитель или сервер, поэтому она тоже не гарантирует правду.
  • Содержимое файла — фактические байты. У большинства форматов в начале записана сигнатура — характерная последовательность байтов, которую формат задаёт своей спецификацией. Это единственный признак, который нельзя подделать простым переименованием.

Логика надёжной проверки такова: содержимое — главный источник истины, MIME-тип — вторичная подсказка, расширение — последняя. На практике разные системы выстраивают эту иерархию по-разному, и именно отсюда возникают расхождения, которые сбивают пользователей.

Магические числа: что записано в начале файла

Термин «магические числа» пришёл из утилиты Unix file, которая исторически сверяла первые байты файла с базой известных сигнатур. Идея простая: разработчики большинства форматов закрепили в спецификации фиксированную «шапку», по которой файл узнаётся однозначно или почти однозначно.

Несколько общеизвестных примеров сигнатур:

Формат Сигнатура в начале файла Комментарий
PNG 89 50 4E 47 0D 0A 1A 0A Байты, соответствующие символам «%PNG» с контрольными байтами
JPEG FF D8 FF Начало маркера изображения; точный подтип определяется дальше
PDF 25 50 44 46 Текст «%PDF-» и номер версии
ZIP (и DOCX, XLSX, JAR) 50 4B 03 04 Сигнатура «PK»; офисные форматы — это ZIP-архивы внутри
Исполняемые файлы Windows 4D 5A Символы «MZ»; тип (EXE, DLL, драйвер) уточняется по заголовку
MP3 FF FB или ID3 Кадр MPEG-аудио или текстовый тег в начале

Обратите внимание на строку про ZIP: файл .docx или .xlsx начинается так же, как обычный архив. Это не совпадение, а следствие формата: современные офисные документы — это ZIP-контейнеры со строго заданной внутренней структурой. Поэтому по первым байтам можно сказать «это ZIP», а чтобы отличить документ от архива, нужно заглянуть внутрь и найти служебные файлы контейнера.

Сигнатуры не всегда находятся в самом начале. У некоторых форматов важные метки расположены со смещением: например, у старых офисных форматов Microsoft (DOC, XLS в версии OLE) сигнатура стоит по фиксированному смещению внутри составного заголовка. Утилита file и библиотеки распознавания учитывают такие правила через базу описаний, где для каждого формата указано, какие байты, на каком смещении и в какой комбинации искать.

Как это делают разные системы

Операционные системы

Windows исторически опирается на расширение: реестр связывает суффикс имени с программой по умолчанию. Это быстро и дёшево, но означает, что переименованный файл «сменит тип» в глазах проводника, хотя байты не изменились. При запуске, однако, система проверяет и содержимое: исполняемый формат проверяется по заголовку, и файл с расширением .txt, внутри которого лежит исполняемый код, просто не запустится как текст.

macOS хранит тип файла в метаданных файловой системы и дополнительно использует расширение и сигнатуры. Linux и другие Unix-подобные системы вообще не считают расширение признаком типа: для них файл — просто поток байтов. Тип определяется при открытии: графический просмотрщик анализирует данные сам, а утилита file сверяет содержимое с базой сигнатур. Именно поэтому в Linux файл без расширения открывается нормально, а в Windows чаще всего «теряет» свою программу.

Браузеры

Браузер получает файл по сети вместе с MIME-типом в заголовке Content-Type. Дальше работает защита: если сервер объявил файл как text/plain, а внутри обнаруживается HTML или скрипт, браузер не станет его исполнять — это защита от атак, когда злоумышленник пытается выдать опасное содержимое за безобидное. Для изображений и медиа браузеры дополнительно анализируют сами данные: картинка с расширением .png, внутри которой лежит JPEG, всё равно отобразится, потому что декодер определил формат по байтам.

При загрузке файлов на сайты проверка обычно двухступенчатая: сначала браузер сообщает MIME-тип и имя файла, затем сервер самостоятельно проверяет содержимое по сигнатуре. Серьёзные сервисы никогда не доверяют только имени или заявленному типу, потому что оба значения контролирует клиент.

Серверы и антивирусы

Веб-сервер определяет MIME-тип исходящего файла чаще всего по расширению через таблицу соответствий. Это работает, пока расширения корректны. Системы безопасности идут глубже: антивирусы разбирают структуру файла, ищут аномалии вроде исполняемого кода, приклеенного к концу изображения, или несоответствия между заявленным и реальным форматом. Именно несовпадение сигнатуры и расширения — один из классических признаков замаскированной вредоносной программы.

Почему признаки могут противоречить друг другу

Расхождение между расширением, MIME-типом и содержимым — не экзотика, а обычная ситуация. Типичные причины:

  • Переименование. Пользователь или программа сменили суффикс, не трогая данные. Файл report.pdf может на деле быть снимком экрана в формате PNG.
  • Неполная загрузка или обрыв передачи. Файл обрезан, и сигнатура в конце (некоторые форматы хранят там указатели и индексы) отсутствует, хотя начало корректно.
  • Конкатенация и контейнеры. К изображению дописан архив или скрипт: первые байты честно говорят «JPEG», но внутри есть лишнее.
  • Ошибки сервера. Неверно настроенная таблица MIME-типов отдаёт архив как текст или наоборот.
  • Маскировка вредоносного файла. Исполняемый файл переименован в документ, чтобы обойти фильтр по расширению.

Из-за этого правило для пользователя простое: если файл «не открывается», не стоит верить его имени. Надёжнее проверить, что внутри, и уже потом решать, чем его открыть.

Как проверить настоящий тип файла самостоятельно

Для разовой проверки не нужны специальные знания — достаточно посмотреть первые байты файла:

  1. В Windows откройте файл в редакторе, который показывает «сырые» байты, например в бесплатном hex-редакторе или через PowerShell-команду чтения первых байтов. Сравните начало с таблицей сигнатур выше: «%PNG» означает PNG, «%PDF» — PDF, «PK» — ZIP-семейство.
  2. В macOS или Linux выполните в терминале команду file имя_файла. Утилита сверит содержимое с базой сигнатур и выведет определённый тип. Это самый быстрый способ.
  3. Без терминала можно открыть файл текстовым редактором: у бинарных форматов начало часто читается как текст (PNG покажет «%PNG», PDF — «%PDF-1.x»). Это грубый, но рабочий метод для явных случаев.

Если определённый по содержимому тип отличается от расширения, просто переименуйте файл в правильный суффикс — в большинстве случаев он откроется. Если же файл не распознаётся вообще, вероятно, он повреждён, обрезан или это формат без общепринятой сигнатуры.

Форматы без надёжной сигнатуры

Не у всех форматов есть однозначная «шапка», и это важное ограничение всего механизма. Текстовые файлы (TXT, CSV, исходный код) состоят из произвольного текста, и определить их «тип» можно только эвристически: по кодировке, по характерным конструкциям, по расширению. JSON узнают по фигурным скобкам и структуре, но это уже анализ, а не поиск фиксированных байтов.

Есть и обратная ситуация: несколько форматов используют одинаковое начало. ZIP-сигнатура «PK» покрывает архивы, офисные документы, некоторые приложения Java и другие контейнеры. В таких случаях программа после проверки сигнатуры разбирает внутреннюю структуру: ищет служебные записи, манифесты, каталоги. Поэтому «определить тип по первым байтам» — это первый шаг, а не вся проверка.

Практические следствия для разных задач

Если вы обычный пользователь

Не переименовывайте расширение наугад в надежде «починить» файл — если проблема в повреждённых данных, смена суффикса ничего не даст. Сначала выясните реальный формат по сигнатуре, затем выставьте правильное расширение. И относитесь настороженно к файлам, чьё имя обещает документ, а система или почтовый клиент предупреждает об исполняемом содержимом: расхождение имени и содержимого — частый признак вредоносной рассылки.

Если вы принимаете файлы от пользователей на своём сервисе

Проверка только по расширению или по присланному браузером MIME-типу — недостаточная мера. Минимальный надёжный набор выглядит так:

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

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

Если вы разбираетесь в цифровых материалах и архивах

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

Типичные ошибки и заблуждения

  • «Расширение определяет тип файла». Оно лишь подсказка. Реальный тип — в содержимом, и переименование не меняет ни байта данных.
  • «MIME-тип из заголовка — это правда». Его выставляет отправитель. Клиент может прислать что угодно, поэтому серверная проверка по сигнатуре обязательна везде, где файлы приходят извне.
  • «Если файл открылся, он безопасен». Открытие изображения с приклеенным к нему исполняемым кодом само по себе безвредно, но такой файл опасен при другом способе обработки. Расхождение форматов — повод для проверки, а не для спокойствия.
  • «Определение по сигнатуре даёт точный формат всегда». У текстовых форматов сигнатуры нет, у контейнеров сигнатура общая для семейства. Точность достигается комбинацией: сигнатура плюс разбор структуры.
  • «Смена расширения может повредить файл». Нет: переименование не затрагивает данные. Вред наносит только изменение содержимого, например сохранение текстовым редактором с перекодировкой.

Что запомнить и что делать дальше

Главный принцип: настоящий тип файла живёт в его байтах, а не в имени. Сигнатура в начале файла — самый надёжный быстрый признак, MIME-тип и расширение — вспомогательные подсказки, которые могут лгать по неведению или намеренно. Чем выше цена ошибки — приём файлов от пользователей, работа с документами из ненадёжных источников, разбор повреждённых данных, — тем меньше стоит доверять имени и тем важнее проверка содержимого.

Практический следующий шаг: если у вас есть файл, который ведёт себя «не как заявлено», проверьте его первые байты командой file (macOS, Linux) или любым hex-просмотрщиком (Windows), сравните результат с таблицей сигнатур и приведите расширение в соответствие с реальным форматом. Если содержимое не распознаётся вовсе — файл повреждён, и переименованием проблему не решить: понадобится инструмент, который умеет восстанавливать данные конкретного формата.

PEFile.ru