Hash update stream: примеры (PHP)

Инкрементальное хеширование потоков с hash_update_stream
Раздел: Хеширование и шифрование
hash_update_stream(HashContext $context, resource $stream, int $length = -1): int
Описание функции hash_update_stream

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

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

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

  • context (ресурс) — контекст хеширования, созданный функцией hash_init(). Обязательный аргумент.
  • handle (ресурс) — открытый поток (например, возвращаемый функцией fopen()). Обязательный аргумент.
  • length (int) — максимальное количество данных для чтения из потока в байтах. По умолчанию -1, что означает чтение до конца потока.

Функция возвращает true в случае успеха или false при возникновении ошибки.

Короткие примеры использования
Пример 1: Базовое использование
<?php
$context = hash_init('sha256');
$handle = fopen('large_file.txt', 'rb');
hash_update_stream($context, $handle);
$hash = hash_final($context);
echo $hash;
fclose($handle);
?>
a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
Пример 2: Чтение ограниченного количества данных
<?php
$context = hash_init('md5');
$handle = fopen('data.txt', 'rb');
// Чтение только первых 1024 байт
hash_update_stream($context, $handle, 1024);
$hash = hash_final($context);
echo $hash;
fclose($handle);
?>
098f6bcd4621d373cade4e832627b4f6
Похожие функции в PHP
  • hash_update() — обновляет контекст хеширования строкой данных. Подходит для работы с данными в виде строк, а не потоков.
  • hash_file() — вычисляет хеш файла напрямую. Удобна для простых случаев, когда не требуется инкрементальная обработка.
  • hash_init() + hash_final() — базовые функции для инкрементального хеширования. hash_update_stream() дополняет их для работы с потоками.

Выбор функции зависит от источника данных: hash_update_stream() оптимальна для потоков, hash_file() — для файлов целиком, hash_update() — для строк.

Альтернативы в других языках

Hash update stream в Python

Модуль hashlib позволяет инкрементальное хеширование через методы update(), принимающие байты. Потоки обрабатываются чтением блоками.

import hashlib
sha256 = hashlib.sha256()
with open('large_file.txt', 'rb') as f:
    for chunk in iter(lambda: f.read(4096), b''):
        sha256.update(chunk)
print(sha256.hexdigest())
a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
JavaScript (Node.js)

Модуль crypto предоставляет потоковые трансформы. Метод update() может принимать данные чанками.

const crypto = require('crypto');
const fs = require('fs');
const hash = crypto.createHash('sha256');
const stream = fs.createReadStream('large_file.txt');
stream.on('data', chunk => hash.update(chunk));
stream.on('end', () => console.log(hash.digest('hex')));
a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890

Hash update stream в MySQL

Функции SHA2() или MD5() вычисляют хеш для строки, но не поддерживают инкрементальную обработку потоков. Для файлов требуется чтение средствами языка приложения.

Типичные ошибки
Ошибка 1: Передача неверного типа ресурса
<?php
$context = hash_init('sha256');
$handle = 'not_a_stream';
// Вызовет предупреждение
hash_update_stream($context, $handle);
?>
Warning: hash_update_stream() expects parameter 2 to be resource, string given
Ошибка 2: Использование закрытого потока
<?php
$context = hash_init('sha256');
$handle = fopen('file.txt', 'rb');
fclose($handle);
// Поток уже закрыт
hash_update_stream($context, $handle);
?>
Warning: hash_update_stream(): supplied resource is not a valid stream resource
Ошибка 3: Отсутствие инициализации контекста
<?php
$handle = fopen('file.txt', 'rb');
// Контекст не создан
hash_update_stream(null, $handle);
?>
Warning: hash_update_stream() expects parameter 1 to be resource, null given
Изменения в последних версиях PHP

Начиная с PHP 8.0, функция выбрасывает исключение Error в случае неверного количества аргументов. Ранее это вызывало предупреждение.

В PHP 8.1 не было значительных изменений в поведении функции. Однако улучшена общая обработка ресурсов, что может повлиять на сообщения об ошибках.

Расширенные примеры
Пример 1: Хеширование нескольких потоков последовательно
Пример php
<?php
$context = hash_init('sha3-512');
$file1 = fopen('part1.bin', 'rb');
$file2 = fopen('part2.bin', 'rb');
hash_update_stream($context, $file1);
hash_update_stream($context, $file2);
$hash = hash_final($context);
echo "Общий хеш: $hash";
fclose($file1);
fclose($file2);
?>
Общий хеш: 9a3b... (хеш конкатенации двух файлов)
Пример 2: Использование с потоком ввода php://input
Пример php
<?php
// Хеширование тела HTTP-запроса
$context = hash_init('sha256');
$input = fopen('php://input', 'rb');
hash_update_stream($context, $input);
$hash = hash_final($context);
header('X-Request-Hash: ' . $hash);
?>
HTTP-заголовок X-Request-Hash содержит хеш тела запроса
Пример 3: Хеширование с одновременной записью в файл
Пример php
<?php
$context = hash_init('crc32b');
$source = fopen('source.iso', 'rb');
$dest = fopen('copy.iso', 'wb');
while (!feof($source)) {
    $buffer = fread($source, 8192);
    fwrite($dest, $buffer);
    // Обновление хеша прочитанным блоком
    hash_update($context, $buffer);
}
$hash = hash_final($context);
echo "Хеш при копировании: $hash";
fclose($source);
fclose($dest);
?>
Хеш при копировании: 12345678
Пример 4: Использование с потоковыми контекстами
Пример php
<?php
$context = hash_init('md5');
$remote = fopen('http://example.com/large.zip', 'rb', false, stream_context_create([]));
hash_update_stream($context, $remote, 1048576); // Только первые 1 МБ
$hash = hash_final($context);
echo "Хеш первых мегабайт: $hash";
fclose($remote);
?>
Хеш первых мегабайт: 5d41402abc4b2a76b9719d911017c592

PHP hash_update_stream function comments

En
Hash update stream Pump data into an active hashing context from an open stream