← Заметки

Проверка контрольной суммы SHA-256 скачанного файла с помощью Python

На этой странице

Чтобы проверить скачанный файл, вычислите его хеш SHA-256 и сравните с ожидаемым значением от издателя, которому вы доверяете. Модуль Python hashlib позволяет обрабатывать двоичные байты порциями. Совпадение подтверждает соответствие этих байтов указанному значению; оно не удостоверяет издателя и не доказывает безопасность программы. Adoptium отдельно описывает проверку подписи.

С какой контрольной суммой сравнивать?

Используйте контрольную сумму именно для скачанного выпуска, ОС, процессора и формата архива. Скрипт выбора выпуска GitHub выбирает URL файла; пример с метаданными Temurin также проверяет синтаксис контрольной суммы. Ни один из них не вычисляет хеш скачанного файла. В инструкции Adoptium по установке из архивов описано получение соответствующей контрольной суммы.

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

Как работает проверка файла?

Проверка формата контрольной суммы, вычисление хеша файла и сравнение результата

Проверьте ожидаемое значение, откройте неизменяемый во время проверки обычный файл в двоичном режиме, обновляйте хеш порциями до EOF и сравните результат. Неверный ввод или ошибка чтения возвращает 2; несовпадение — 1; только совпадение — 0. На схеме цикл чтения порциями сведён к одному шагу. Не изменяйте и не заменяйте файл во время проверки или после неё до использования. Этот инструмент не обеспечивает атомарную проверку с последующим выполнением.

Запуск проверки без дополнительных пакетов

Используйте Python 3.11 или новее и сохраните приведённый ниже код в verify-sha256.py. Следующие команды рассчитаны на оболочку POSIX. Программа читает локальные файлы; она не скачивает, не распаковывает и не запускает их. Она следует по символической ссылке, если та указывает на обычный файл. На вход принимается одно шестнадцатеричное значение из 64 символов, в том числе в верхнем регистре, а не файл со списком контрольных сумм, имя файла или URL.

verify-sha256.py

import hashlib
from pathlib import Path
import re
import sys


def main(argv):
    if len(argv) != 3 or not re.fullmatch(r"[0-9a-fA-F]{64}", argv[1]):
        print("usage: verify-sha256.py EXPECTED_SHA256 FILE", file=sys.stderr)
        return 2
    path = Path(argv[2])
    try:
        if not path.is_file():
            raise OSError("expected an existing regular file")
        digest = hashlib.sha256()
        with path.open("rb") as source:
            for chunk in iter(lambda: source.read(1024 * 1024), b""):
                digest.update(chunk)
    except OSError as error:
        print(f"READ ERROR: {error}", file=sys.stderr)
        return 2
    if digest.hexdigest() != argv[1].lower():
        print("MISMATCH", file=sys.stderr)
        return 1
    print("OK")
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))

Режим rb сохраняет исходные байты, включая окончания строк. Каждая операция чтения запрашивает не более 1 MiB; файл целиком в память не загружается. Неверные контрольные суммы отклоняются до открытия пути. Отсутствующие пути, каталоги и ошибки чтения возвращают один статус 2. Именованные каналы и файлы устройств не входят в поддерживаемую категорию обычных файлов.

Воспроизведение совпадения и изменения файла

Используйте новый пустой каталог. Эти тестовые данные создают sample.bin с тремя байтами abc и changed.bin с abcd. Фиксированный хеш в команде относится только к abc; это не контрольная сумма архива JDK.

make-samples.py

from pathlib import Path

Path("sample.bin").write_bytes(b"abc")
Path("changed.bin").write_bytes(b"abcd")
python3 make-samples.py
expected='ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
python3 verify-sha256.py "$expected" sample.bin
python3 verify-sha256.py "$expected" changed.bin
printf 'exit=%s\n' "$?"

Файл с совпадающим хешем выводит OK. Изменённый файл выводит MISMATCH в stderr, а последняя команда — exit=1. При использовании set -e ожидаемое несовпадение требует явного if или другой ветви обработки ошибки; иначе оболочка может завершиться до вывода статуса.

Статус Значение Следующее действие
0 Хеш совпадает с переданным ожидаемым значением Продолжайте только при получении ожидаемого значения из доверенного источника
1 Хеши различаются Прекратите использовать файл; проверьте выбранный файл выпуска и загрузку
2 Неверные аргументы, синтаксис контрольной суммы или ошибка чтения файла Исправьте ввод или доступ к файлу и повторите попытку

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

Обсуждение

Посмотреть на GitHub ↗