Hash init: примеры (PHP)
Инкрементальное хеширование через hash_init в PHP
Раздел: Хеширование и шифрование
hash_init(string $algo, int $flags = 0, string $key = "", array $options = []): HashContextФункция hash_init инициализирует инкрементальный контекст хеширования. Она используется, когда данные для хеширования поступают частями, а не целиком. Это эффективно для обработки больших файлов или потоков данных без необходимости загружать их полностью в память.
Аргументы функции
- algo (string): Имя выбранного алгоритма хеширования (например, 'md5', 'sha256', 'sha3-512'). Список доступных алгоритмов можно получить с помощью функции hash_algos().
- flags (int): Необязательные флаги, изменяющие поведение функции.
- HASH_HMAC: При использовании этого флага требуется дополнительный аргумент key. Позволяет вычислять HMAC (Hash-based Message Authentication Code).
- key (string): Необязательный ключ для HMAC. Требуется, если установлен флаг HASH_HMAC. Если флаг установлен, но ключ не передан, будет выброшено исключение.
Простые примеры использования
Пример 1: Базовое использование
Хеширование строки по частям.
<?php
$context = hash_init('sha256');
hash_update($context, 'Hello, ');
hash_update($context, 'world!');
$result = hash_final($context);
echo $result;
?>315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
Пример 2: Использование с HMAC
Вычисление HMAC для аутентификации сообщения.
<?php
$key = 'secret-key';
$context = hash_init('sha256', HASH_HMAC, $key);
hash_update($context, 'Важное сообщение');
$hmac = hash_final($context);
echo $hmac;
?>9e0e5f9c7c2a1e5b8b5d9f8a2c3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2
Похожие функции в PHP
В PHP существуют другие функции для работы с хешами:
- hash(): Вычисляет хеш из строки целиком. Используется, когда все данные уже находятся в памяти. Проще в использовании, но не подходит для потоковой обработки.
- hash_file(): Вычисляет хеш-сумму файла. Удобна для работы с файлами, но также требует указания полного пути. Внутри может использовать механизм, схожий с hash_init.
- md5(), sha1(): Устаревшие функции для конкретных алгоритмов. Не поддерживают инкрементальное хеширование и менее безопасны для современных задач. Рекомендуется использовать hash() или hash_init с современными алгоритмами (SHA-2, SHA-3).
hash_init предпочтительнее использовать при потоковой обработке данных или работе с большими объемами информации.
Аналоги в других языках
Python (модуль hashlib)
import hashlib
# Инкрементальное хеширование
hasher = hashlib.sha256()
hasher.update(b'Hello, ')
hasher.update(b'world!')
result = hasher.hexdigest()
print(result) # 315f5bdb...
# HMAC (отдельный модуль hmac)
import hmac
hmac_digest = hmac.new(b'secret-key', b'Важное сообщение', hashlib.sha256).hexdigest()
print(hmac_digest)JavaScript (Node.js, crypto модуль)
const crypto = require('crypto');
// Инкрементальное хеширование
const hash = crypto.createHash('sha256');
hash.update('Hello, ');
hash.update('world!');
let result = hash.digest('hex');
console.log(result); // 315f5bdb...
// HMAC
const hmac = crypto.createHmac('sha256', 'secret-key');
hmac.update('Важное сообщение');
let hmacResult = hmac.digest('hex');
console.log(hmacResult);Hash init в MySQL
Функции хеширования в MySQL, такие как SHA2(), работают только с готовыми данными. Инкрементальное хеширование на уровне запросов не поддерживается.
SELECT SHA2('Hello, world!', 256);
-- Результат: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3Распространенные ошибки
1. Передача неверного имени алгоритма
<?php
$context = hash_init('неизвестный_алгоритм');
?>Warning: hash_init(): Unknown hashing algorithm: неизвестный_алгоритм
2. Отсутствие ключа при использовании HASH_HMAC
<?php
$context = hash_init('sha256', HASH_HMAC);
?>Warning: hash_init(): HMAC requested without a key
3. Попытка обновления или финализации неверного ресурса/объекта
<?php
$context = null;
hash_update($context, 'data');
?>TypeError: hash_update(): Argument #1 ($context) must be of type HashContext, null given
4. Использование результата hash_final() для обновлений
<?php
$ctx = hash_init('md5');
hash_update($ctx, 'test');
$result = hash_final($ctx);
// Контекст $ctx теперь недействителен
hash_update($ctx, 'more'); // Ошибка
?>Fatal error: Uncaught TypeError: hash_update(): Argument #1 ($context) must be of type HashContext, bool given
Изменения в последних версиях PHP
- В PHP 8.0 типичные предупреждения при передаче неверных аргументов (например, неизвестный алгоритм) были преобразованы в исключение ValueError.
- Начиная с PHP 8.1.0, возвращаемый тип изменился с resource на объект HashContext. Это изменение направлено на устранение устаревших ресурсов.
<?php
// До PHP 8.1
// $context = hash_init(...) возвращал ресурс (resource)
// С PHP 8.1
$context = hash_init('sha256');
var_dump($context);
?>object(HashContext)#1 (0) {
}Расширенные примеры применения
Обработка большого файла по частям
Пример php
<?php
function getFileHash($filename, $algorithm = 'sha256') {
if (!file_exists($filename)) {
throw new Exception("Файл не найден.");
}
$handle = fopen($filename, 'rb');
if (!$handle) {
throw new Exception("Не удалось открыть файл.");
}
$context = hash_init($algorithm);
while (!feof($handle)) {
$chunk = fread($handle, 8192); // Чтение по 8 КБ
hash_update($context, $chunk);
}
fclose($handle);
return hash_final($context);
}
// Использование
echo getFileHash('large_video.mp4', 'sha3-512');
?>Сравнение файлов без загрузки в память
Пример php
<?php
function areFilesIdentical($file1, $file2) {
$ctx1 = hash_init('sha256');
$ctx2 = hash_init('sha256');
$fh1 = fopen($file1, 'rb');
$fh2 = fopen($file2, 'rb');
while (!feof($fh1) && !feof($fh2)) {
hash_update($ctx1, fread($fh1, 4096));
hash_update($ctx2, fread($fh2, 4096));
}
fclose($fh1);
fclose($fh2);
return hash_final($ctx1) === hash_final($ctx2);
}
?>Построение дерева Меркла (упрощенный пример)
Пример php
<?php
function merkleLeafHash($data) {
return hash('sha256', $data, true); // raw_output = true
}
function merkleParentHash($left, $right) {
$context = hash_init('sha256');
hash_update($context, $left);
hash_update($context, $right);
return hash_final($context, true);
}
// Пример с двумя блоками данных
$leaf1 = merkleLeafHash('Транзакция 1');
$leaf2 = merkleLeafHash('Транзакция 2');
$root = merkleParentHash($leaf1, $leaf2);
echo bin2hex($root);
?>PHP hash_init function comments
En
Hash init Initialize an incremental hashing context