Во многих случаях, особенно при передаче ID пользователя в URL или JavaScript, нежелательно раскрывать внутренние значения из базы данных. Простой числовой идентификатор, например 123
, может позволить злоумышленнику перебором найти другие записи, что открывает дверь для атаки по перебору (IDOR – Insecure Direct Object Reference).
Чтобы избежать этого, можно применить шифрование ID с помощью симметричного алгоритма, например AES. Это не просто "маскировка", а полноценное преобразование, которое нельзя расшифровать без ключа.
Принцип работы
- ID пользователя (или массива ID) превращается в строку.
- Она шифруется с использованием алгоритма AES-256-CBC.
- В качестве дополнительной защиты используется случайный вектор инициализации (IV), который объединяется с зашифрованными данными.
- Полученная строка кодируется в base64 для безопасной передачи в URL.
На выходе мы получаем токен, который невозможно расшифровать без знания ключа и алгоритма.
Реализация: метод encryptId()
public static function encryptId($ids)
{
$key = self::KEY;
// 1. Подготовка данных: если массив — объединить через запятую
$data = is_array($ids) ? implode(',', $ids) : (string)$ids;
// 2. Генерация случайного IV (16 байт для AES-256-CBC)
$iv = random_bytes(16);
// 3. Шифрование данных
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
// 4. Склейка IV + шифртекст и кодирование в base64
return base64_encode($iv . $encrypted);
}
Каждый вызов создаёт разный токен, даже для одного и того же ID, за счёт случайного IV.
Расшифровка: метод decryptToken()
public static function decryptToken($token)
{
$key = self::KEY;
// Декодируем GET-строку и base64
$token = urldecode($token);
$token = str_replace(' ', '+', $token);
$raw = base64_decode($token, true);
if ($raw === false || strlen($raw) < 17) {
return null;
}
// Извлечение IV и зашифрованного текста
$iv = substr($raw, 0, 16);
$encrypted = substr($raw, 16);
// Расшифровка
$decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
if ($decrypted === false) {
return null;
}
// Разделение обратно в массив или число
$ids = array_map('intval', explode(',', $decrypted));
return count($ids) === 1 ? $ids[0] : $ids;
}
Этот метод «понимает», была ли изначально передана одна ID или массив, и возвращает корректный тип.
Применение
// Зашифровать ID
$token = MyHelper::encryptId(123); // → безопасный токен
// Использовать токен в URL
echo '<a href="/user/view/?id=' . urlencode($token) . '">Открыть профиль</a>';
// При загрузке страницы
$id = MyHelper::decryptToken($_GET['id']);
Безопасность
- Используется AES-256-CBC, один из самых безопасных симметричных алгоритмов.
- IV генерируется случайно каждый раз, что исключает повторяемость результата.
- Без ключа (
KEY
) расшифровка невозможна. - Ключ должен быть надёжным (32 байта) и храниться безопасно (например, в
.env
илиwa-config
).
Вывод
Шифрование ID — это простое, но эффективное средство защиты от перебора и утечки внутренней структуры базы данных. Использование encryptId()
и decryptToken()
позволяет надёжно скрыть реальные идентификаторы пользователей при передаче данных через URL, JavaScript и API.