Random bytes: примеры (PHP)

Полное руководство по работе с random_bytes в PHP
Раздел: Безопасность
random_bytes(int $length): string
Введение в функцию random_bytes

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

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

Синтаксис и аргументы
random_bytes(int $length): string

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

  • $length (int) - целое положительное число, определяющее количество байтов для генерации. Возвращаемая строка будет содержать ровно столько байтов.

Функция возвращает строку, состоящую из запрошенного количества случайных байтов. В случае ошибки (например, если не удалось получить достаточно энтропии) выбрасывается исключение типа \Exception, а в PHP 8.2+ - более специфичные \Random\RandomException или \ValueError для недопустимой длины.

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

Ниже приведены простые примеры генерации случайных байтов.

Генерация 16 байт
$bytes = random_bytes(16);
echo bin2hex($bytes); // Для удобного вывода
Пример результата: 1a2b3c4d5e6f7890a1b2c3d4e5f60718
Генерация 32 байт (например, для ключа)
$key = random_bytes(32);
var_dump(base64_encode($key));
Пример результата: string(44) "L0km9Pq7XjvWlNcRzTbYwAeFgHjKlMnOpQrStUvWxYz0="
Использование в условии
try {
$token = random_bytes(20);
} catch (\Exception $e) {
// Обработка ошибки (крайне маловероятна в нормальных условиях)
$token = openssl_random_pseudo_bytes(20); // Резервный вариант
}
echo 'Токен: ' . bin2hex($token);
Пример результата: Токен: 8f9e7d6c5b4a39281726354433221100ffeeddcc
Альтернативы и похожие функции в PHP
  • openssl_random_pseudo_bytes($length, &$crypto_strong) - генерирует псевдослучайную строку байт, используя OpenSSL. Второй аргумент позволяет проверить, был ли использован криптографически безопасный алгоритм. Использовать предпочтительно, если требуется совместимость со старыми версиями PHP (<7) или необходима интеграция с логикой OpenSSL.
  • random_int($min, $max) - "сестра" функции random_bytes, генерирует криптографически безопасное случайное целое число в заданном диапазоне. Использовать предпочтительно для получения случайных чисел (например, для выбора элемента массива, генерации кода), а не сырых байтов.
  • rand() и mt_rand() - старые генераторы псевдослучайных чисел. Они не являются криптографически безопасными и их предсказуемость высока. Использовать только в некритичных для безопасности задачах (например, симуляции, игры, тестовые данные).
Аналоги в других языках программирования
Python (модуль secrets)
import secrets
# Генерация 16 байт
bytes_data = secrets.token_bytes(16)
print(bytes_data.hex())
c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0
JavaScript (Web Crypto API в браузерах и Node.js)
// Браузер и Node.js
const array = new Uint8Array(16);
crypto.getRandomValues(array);
console.log(Array.from(array, byte => byte.toString(16).padStart(2, '0')).join(''));
1f2e3d4c5b6a7988f7e6d5c4b3a29180
MySQL (функция RANDOM_BYTES)
-- Генерация 32 байт, результат в бинарном виде
SELECT HEX(RANDOM_BYTES(32)) as random_data;
random_data
----------------------------------
A1B2C3D4E5F67890123456789ABCDEF0...

Отличия от PHP: В Python и JS (Web Crypto) подход похож - есть выделенный криптографический API. В MySQL функция работает в контексте СУБД. Главное отличие PHP - в простом и унифицированном синтаксисе без необходимости инициализации сложных объектов.

Типичные ошибки и их обработка
Передача недопустимого значения длины
// PHP 8+
try {
$data = random_bytes(0); // Длина должна быть >= 1
} catch (\ValueError $e) {
echo 'Ошибка: ' . $e->getMessage();
}
Ошибка: random_bytes(): Argument #1 ($length) must be greater than 0
Ошибка получения энтропии (крайне редкая)
try {
// Запрос очень большого объема данных может теоретически вызвать проблему
$huge = random_bytes(PHP_INT_MAX);
} catch (\Random\RandomException $e) { // PHP 8.2+
echo 'Не удалось получить безопасные случайные данные: ' . $e->getMessage();
} catch (\Exception $e) { // Для PHP < 8.2
echo 'Общая ошибка: ' . $e->getMessage();
}
Не удалось получить безопасные случайные данные: Random number generation failed
Неправильная интерпретация результата
$bytes = random_bytes(4);
echo $bytes; // Прямой вывод может показать нечитаемые символы
echo 'Правильно: ' . bin2hex($bytes); // Так корректно
Правильно: 4a5b6c7d
Изменения в последних версиях PHP
  • PHP 8.2: Введено новое исключение \Random\RandomException, которое выбрасывается при неудачной генерации, вместо общего \Exception. Это позволяет более точно отлавливать ошибки, связанные именно с генерацией случайных чисел.
  • PHP 8.0: Для недопустимых аргументов (например, длина < 1) теперь выбрасывается исключение типа \ValueError. В более ранних версиях это могло приводить к ошибкам уровня E_WARNING.
  • PHP 7.0: Функция random_bytes() была первоначально введена как часть расширения CSPRNG (Cryptographically Secure Pseudo-Random Number Generator).
Расширенные и практические примеры
Генерация безопасного пароля
Пример php
function generatePassword(int $length = 16): string {
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()-_=+[]{}|;:,.<>?';
$password = '';
$charCount = strlen($chars);
// Используем random_int для выбора символов на основе безопасных байтов
for ($i = 0; $i < $length; $i++) {
$password .= $chars[random_int(0, $charCount - 1)];
}
return $password;
}
echo generatePassword(12);
Пример: kP8@m#dL2!vQ
Создание UUID версии 4
Пример php
function generateUUIDv4(): string {
$data = random_bytes(16);
// Установка версии (4) и варианта (RFC 4122)
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // version 4
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // variant RFC 4122
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
echo generateUUIDv4();
Пример: 550e8400-e29b-41d4-a716-446655440000
Генерация соли для хеширования пароля
Пример php
// Соль для password_hash с PASSWORD_DEFAULT (использует bcrypt)
$salt = random_bytes(16); // bcrypt внутренне использует 16 байт соли
$password = 'user_password123';
$hash = password_hash($password, PASSWORD_DEFAULT); // Соль генерируется автоматически и безопасно
// Но можно явно сгенерировать для других алгоритмов, например, для ручного HMAC
$manualSalt = base64_encode(random_bytes(32));
echo 'Соль для HMAC: ' . $manualSalt;
Пример: Соль для HMAC: zXl4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+QkZKT
Создание случайного начального вектора (IV) для шифрования
Пример php
$method = 'aes-256-cbc';
$ivLength = openssl_cipher_iv_length($method);
$iv = random_bytes($ivLength);
$data = 'Секретное сообщение';
$key = random_bytes(32); // Ключ для AES-256
$encrypted = openssl_encrypt($data, $method, $key, 0, $iv);
echo 'Зашифровано. IV (hex): ' . bin2hex($iv);
IV (hex): 1234567890abcdef1234567890abcdef
Имитация броска нескольких кубиков
Пример php
function rollDice(int $count, int $sides = 6): array {
$results = [];
for ($i = 0; $i < $count; $i++) {
$results[] = random_int(1, $sides);
}
return $results;
}
print_r(rollDice(5, 20)); // Бросить 5 двадцатигранных кубиков
Array
(
[0] => 14
[1] => 3
[2] => 20
[3] => 8
[4] => 11
)

PHP random_bytes function comments

En
Random bytes Generates cryptographically secure pseudo-random bytes