Crc32: примеры (PHP)

CRC32 в PHP: полное руководство с примерами и особенностями
Раздел: Хеширование и шифрование
crc32(string $string): int
Описание функции crc32

Функция crc32 вычисляет полиномиальную контрольную сумму для строки, используя 32-битный алгоритм Cyclic Redundancy Check (CRC). Этот алгоритм часто применяется для проверки целостности данных, но не для криптографических целей, так как не является устойчивым к коллизиям.

Основное применение - быстрая проверка изменений в данных, создание коротких хешей для сравнения или использование в сетевых протоколах.

Синтаксис и аргументы

Сигнатура функции:
crc32(string $string): int

Функция принимает один обязательный параметр:

  • $string (string) - строка, для которой вычисляется контрольная сумма CRC32.

Возвращаемое значение - целое число (int) со знаком, представляющее контрольную сумму CRC32. На 32-битных системах результат может быть отрицательным числом.

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

Код:

$str = "Hello, world!";
$crc = crc32($str);
echo "CRC32: " . $crc;
// Для получения шестнадцатеричного представления
printf("CRC32 (hex): %x", $crc);

Результат:

CRC32: -1372190028
CRC32 (hex): ae1992b4
Сравнение контрольных сумм

Код:

$data1 = "Test string";
$data2 = "Test string";
$data3 = "Test string "; // с пробелом в конце

$crc1 = crc32($data1);
$crc2 = crc32($data2);
$crc3 = crc32($data3);

var_dump($crc1 === $crc2); // идентичные строки
var_dump($crc1 === $crc3); // разные строки

Результат:

bool(true)
bool(false)
Похожие функции в PHP

PHP предлагает несколько функций для хеширования и создания контрольных сумм:

  • md5() - вычисляет MD5-хеш строки. Возвращает 32-символьный шестнадцатеричный номер. Быстрее, чем crypt(), но также не рекомендуется для безопасности.
  • sha1() - вычисляет SHA1-хеш строки. Возвращает 40-символьный шестнадцатеричный номер. Надежнее MD5, но также имеет уязвимости.
  • hash() - универсальная функция для вычисления хешей с использованием различных алгоритмов (crc32, md5, sha256 и др.). Для CRC32: hash('crc32', $string) возвращает 8-символьное шестнадцатеричное значение без знака.

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

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

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

Crc32 в Python

Модуль zlib или binascii:

import zlib
str_data = b"Hello, world!"
crc_value = zlib.crc32(str_data)
print(f"CRC32: {crc_value}")
print(f"CRC32 (hex): {crc_value & 0xFFFFFFFF:08x}")
CRC32: 2923460726
CRC32 (hex): ae1992b4

Crc32 в Javascript

Нет встроенной функции, но можно использовать сторонние библиотеки или реализовать самостоятельно:

// Пример с использованием библиотеки crc-32
// npm install crc-32
// const CRC32 = require('crc-32');
// let crc = CRC32.str("Hello, world!");
// console.log(crc); // -1372190028

Crc32 в MySQL

Функция CRC32():

SELECT CRC32('Hello, world!');
-- Результат: 2923460726 (беззнаковый)
2923460726

Основное отличие PHP crc32 от других реализаций - возврат знакового целого на 32-битных системах, в то время как другие языки часто возвращают беззнаковое значение.

Типичные ошибки
Неправильное сравнение контрольных сумм

При сравнении результатов crc32 на разных системах (32-битных и 64-битных) могут возникнуть проблемы из-за разного представления отрицательных чисел.

// На 32-битной системе
$crc = crc32("test");
// Может вернуть отрицательное число, например -662733300
// На 64-битной системе та же строка вернет 3632233996
// Прямое сравнение не сработает

Решение: использовать sprintf() для получения шестнадцатеричного представления или преобразование в беззнаковое число:

$crc = crc32("test");
$crc_unsigned = sprintf("%u", $crc);
echo $crc_unsigned; // Всегда беззнаковое представление
Использование для криптографических целей

CRC32 не предназначен для безопасности:

// НЕПРАВИЛЬНО: использование crc32 для хеширования паролей
$password_hash = crc32($password);
// Легко подобрать коллизии
Изменения в последних версиях PHP

Функция crc32 не претерпела значительных изменений в последних версиях PHP. Поведение функции остается стабильным на протяжении многих релизов.

Начиная с PHP 7, все целочисленные значения имеют разрядность 64-бит на всех поддерживаемых платформах, что упрощает работу с результатами crc32 и уменьшает проблемы с переносимостью между 32-битными и 64-битными системами.

В PHP 8 не было внесено изменений в работу функции crc32, что свидетельствует о ее зрелости и стабильности.

Расширенные примеры
Проверка целостности данных

CRC32 может использоваться для быстрой проверки неизменности данных:

Пример php
function createDataPacket($data) {
    $crc = crc32($data);
    return $data . pack('V', $crc); // Добавляем CRC32 в конец данных
}

function verifyDataPacket($packet) {
    if (strlen($packet) < 4) return false;
    
    $data = substr($packet, 0, -4);
    $received_crc = unpack('V', substr($packet, -4))[1];
    $calculated_crc = crc32($data);
    
    // Приведение к беззнаковому виду для сравнения
    $received_crc_unsigned = sprintf("%u", $received_crc);
    $calculated_crc_unsigned = sprintf("%u", $calculated_crc);
    
    return $received_crc_unsigned === $calculated_crc_unsigned;
}

$original = "Important data";
$packet = createDataPacket($original);
echo "Пакет с CRC: " . bin2hex($packet) . "\n";
echo "Проверка оригинала: " . (verifyDataPacket($packet) ? "OK" : "FAIL") . "\n";

// Изменяем пакет
$tampered = substr($packet, 0, -5) . "X" . substr($packet, -4);
echo "Проверка измененного: " . (verifyDataPacket($tampered) ? "OK" : "FAIL") . "\n";
Пакет с CRC: 496d706f7274616e742064617461b49219ae
Проверка оригинала: OK
Проверка измененного: FAIL
Создание быстрого индекса для сравнения файлов
Пример php
function getFileCRC($filename, $chunkSize = 8192) {
    if (!file_exists($filename)) return false;
    
    $crc = 0;
    $fp = fopen($filename, 'rb');
    
    while (!feof($fp)) {
        $data = fread($fp, $chunkSize);
        $crc = crc32($data, $crc);
    }
    
    fclose($fp);
    return $crc;
}

// Сравнение двух файлов по CRC32
$file1 = 'file1.txt';
$file2 = 'file2.txt';

$crc1 = getFileCRC($file1);
$crc2 = getFileCRC($file2);

if ($crc1 !== false && $crc2 !== false) {
    echo "Файл 1 CRC: " . sprintf("%u", $crc1) . "\n";
    echo "Файл 2 CRC: " . sprintf("%u", $crc2) . "\n";
    echo "Файлы " . ($crc1 === $crc2 ? "идентичны" : "различаются") . "\n";
}
Генерация короткого уникального идентификатора
Пример php
function shortHash($data, $length = 8) {
    $crc = crc32($data);
    // Преобразуем в беззнаковое число и затем в шестнадцатеричное
    $hex = dechex(sprintf("%u", $crc));
    // Возвращаем указанное количество символов
    return substr($hex, 0, $length);
}

$id1 = shortHash("user@example.com");
$id2 = shortHash("user@example.com", 4);
$id3 = shortHash("another@domain.com");

echo "ID1 (8 chars): $id1\n";
echo "ID2 (4 chars): $id2\n";
echo "ID3 (8 chars): $id3\n";
ID1 (8 chars): 8e657d77
ID2 (4 chars): 8e65
ID3 (8 chars): 9a3e8a9f
Использование в реализации алгоритмов сжатия

CRC32 часто используется в форматах архивов и протоколах передачи данных:

Пример php
// Упрощенная эмуляция проверки данных по примеру ZIP
function simulateZipCheck($compressedData, $originalCrc) {
    // В реальности здесь была бы декомпрессия
    $calculatedCrc = crc32($compressedData);
    
    $originalUnsigned = sprintf("%u", $originalCrc);
    $calculatedUnsigned = sprintf("%u", $calculatedCrc);
    
    return $originalUnsigned === $calculatedUnsigned;
}

$data = "Compressed data here";
$storedCrc = crc32($data); // Эмуляция CRC, записанного в архив

// Проверка целостности
$isValid = simulateZipCheck($data, $storedCrc);
echo "Данные архива: " . ($isValid ? "не повреждены" : "повреждены") . "\n";

PHP crc32 function comments

En
Crc32 Calculates the crc32 polynomial of a string