Sha1 file: примеры (PHP)

Руководство по функции sha1_file в PHP 8
Раздел: Хеширование и шифрование
sha1_file(string filename [, bool binary]): string|false

Функция sha1_file в PHP

Функция sha1_file() вычисляет SHA1-хеш файла. Она используется для получения уникального хеш-идентификатора содержимого файла. Этот идентификатор можно применять для проверки целостности данных, сравнения файлов или создания контрольных сумм.

Аргументы функции

Функция принимает до двух параметров.

filename (обязательный): Путь к файлу, для которого вычисляется хеш. Если указан URL, функция попытается открыть поток через обертку URL.

binary (опциональный, по умолчанию false): Логический параметр. Если установлен в true, функция возвращает необработанный бинарный результат длиной 20 символов. Если false (по умолчанию), возвращается шестнадцатеричная строка длиной 40 символов.

Простые примеры использования

Пример 1: Получение хеша в шестнадцатеричном формате
<?
$hash = sha1_file('document.pdf');
echo $hash;
?>
da39a3ee5e6b4b0d3255bfef95601890afd80709
Пример 2: Получение бинарного хеша
<?
$binary_hash = sha1_file('image.jpg', true);
echo 'Длина бинарного хеша: ' . strlen($binary_hash);
?>
Длина бинарного хеша: 20
Пример 3: Проверка целостности файла
<?
$expected_hash = '5ba93c9db0cff93f52b521d7420e43f6eda2784f';
$actual_hash = sha1_file('archive.zip');
if ($actual_hash === $expected_hash) {
    echo 'Файл не изменен.';
} else {
    echo 'Файл поврежден или изменен.';
}
?>
Файл не изменен.

Альтернативные функции в PHP

PHP предлагает несколько функций для хеширования файлов, каждая со своими особенностями.

Вычисляет MD5-хеш файла. Алгоритм MD5 считается криптографически нестойким для целей безопасности, но может быть полезен для быстрой проверки целостности в неопасных сценариях. Возвращает 32-символьную шестнадцатеричную строку.

Более универсальная функция. Позволяет вычислять хеш, используя множество алгоритмов (например, sha256, sha512, ripemd160). Функцию sha1_file() можно считать частным случаем hash_file('sha1', $filename). Для новых проектов, особенно требующих безопасности, предпочтительнее использовать hash_file() с более стойким алгоритмом, таким как sha256.

Функция работает со строками, но в комбинации с file_get_contents() может использоваться для файлов. CRC32 создает 32-битную контрольную сумму, которая не является криптографическим хешем. Она применяется для быстрого обнаружения случайных изменений данных (например, в сетевых пакетах или архивах).

Аналоги в других языках

Sha1 file в Python

Используется модуль hashlib. Отличие: требует явного открытия и чтения файла блоками для больших файлов.

import hashlib
def sha1_of_file(filename):
    sha1 = hashlib.sha1()
    with open(filename, 'rb') as f:
        while chunk := f.read(8192):
            sha1.update(chunk)
    return sha1.hexdigest()

print(sha1_of_file('test.txt'))
da39a3ee5e6b4b0d3255bfef95601890afd80709
JavaScript (Node.js)

Используется модуль crypto. Функция создает хеш из содержимого файла асинхронно.

const crypto = require('crypto');
const fs = require('fs');

function sha1File(filePath) {
    return new Promise((resolve, reject) => {
        const hash = crypto.createHash('sha1');
        const stream = fs.createReadStream(filePath);
        stream.on('data', chunk => hash.update(chunk));
        stream.on('end', () => resolve(hash.digest('hex')));
        stream.on('error', reject);
    });
}

sha1File('test.txt').then(console.log);
da39a3ee5e6b4b0d3255bfef95601890afd80709

Sha1 file в MySQL

Функция SHA1() работает только со строками. Для файлов необходимо сначала загрузить содержимое в базу данных.

SELECT SHA1(LOAD_FILE('/tmp/test.txt')) AS file_hash;
+------------------------------------------+
| file_hash                                |
+------------------------------------------+
| da39a3ee5e6b4b0d3255bfef95601890afd80709 |
+------------------------------------------+

Типичные ошибки

Ошибка: Файл не существует или нет прав на чтение

Функция возвращает false и генерирует предупреждение уровня E_WARNING.

<?
$result = sha1_file('/несуществующий/файл.txt');
var_dump($result);
?>
Warning: sha1_file(/несуществующий/файл.txt): Failed to open stream: No such file or directory in ...
bool(false)
Ошибка: Неверный тип аргумента

Передача аргумента неверного типа приводит к ошибке TypeError в строгом режиме.

<?
declare(strict_types=1);
try {
    sha1_file(null);
} catch (TypeError $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
?>
Ошибка: sha1_file(): Argument #1 ($filename) must be of type string, null given
Ложная интерпретация: Хеш пустого файла

Хеш пустого файла всегда одинаков, что иногда не ожидается.

<?
file_put_contents('empty.txt', '');
echo sha1_file('empty.txt');
?>
da39a3ee5e6b4b0d3255bfef95601890afd80709

Изменения в последних версиях PHP

В PHP 8.0 сигнатура функции была приведена к строгой типизации. Аргумент $filename теперь имеет тип string, а $binary - bool. Передача значений других типов вызывает TypeError. До PHP 8.0 такие аргументы неявно преобразовывались в нужный тип.

В PHP 7.1 была добавлена возможность указывать $binary как строгий boolean. Ранее небулевые значения могли преобразовываться.

Расширенные примеры применения

Сравнение содержимого двух каталогов
Пример php
<?
function getDirHash($dirPath) {
    $hashes = [];
    $files = scandir($dirPath);
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        $fullPath = $dirPath . DIRECTORY_SEPARATOR . $file;
        if (is_file($fullPath)) {
            $hashes[$file] = sha1_file($fullPath);
        }
    }
    ksort($hashes);
    return sha1(implode('', $hashes)); // Хеш от конкатенации всех хешей файлов
}

$hash1 = getDirHash('dir1');
$hash2 = getDirHash('dir2');
echo 'Каталоги идентичны по содержимому файлов: ' . ($hash1 === $hash2 ? 'Да' : 'Нет');
?>
Каталоги идентичны по содержимому файлов: Нет
Создание токена для инвалидации кэша браузера
Пример php
<?
$cssFile = 'styles.css';
$versionToken = substr(sha1_file($cssFile), 0, 8); // Берем первые 8 символов
?>
Поиск дубликатов файлов в каталоге
Пример php
<?
$dir = 'uploads';
$fileHashMap = [];
$duplicates = [];

$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
foreach ($iterator as $file) {
    if ($file->isFile()) {
        $filePath = $file->getPathname();
        $hash = sha1_file($filePath);
        if (isset($fileHashMap[$hash])) {
            $duplicates[$hash][] = $filePath;
        } else {
            $fileHashMap[$hash] = $filePath;
        }
    }
}

foreach ($duplicates as $hash => $paths) {
    echo "Дубликаты (хеш $hash):
"; foreach ($paths as $path) { echo " - $path
"; } } ?>
Дубликаты (хеш a94a8fe5ccb19ba61c4c0873d391e987982fbbd3):
- uploads/image_copy.jpg
- uploads/image.jpg
Валидация загружаемого файла по белому списку хешей
Пример php
<?
$allowedHashes = [
    '5ba93c9db0cff93f52b521d7420e43f6eda2784f',
    'd6f107c3c9b7e3b3e8e5e8e3c3b9b7e3b3e8e5e8'
];

$uploadedFile = $_FILES['document']['tmp_name'];
$uploadedHash = sha1_file($uploadedFile);

if (in_array($uploadedHash, $allowedHashes, true)) {
    echo 'Файл разрешен для загрузки.';
} else {
    echo 'Загрузка файла запрещена.';
}
?>
Файл разрешен для загрузки.

PHP sha1_file function comments

En
Sha1 file Calculate the sha1 hash of a file