Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як шифрувати дані в Laravel через Crypt і як змінити ключ, не втративши вже зашифроване?

Шифрування в Laravel - симетричне, з ключем APP_KEY, алгоритм за замовчуванням AES-256-CBC з підписом HMAC (чи AES-GCM з вбудованою автентифікацією). Зашифроване значення не можна ні прочитати, ні непомітно змінити без ключа.

use Illuminate\Support\Facades\Crypt;

$token = Crypt::encryptString($apiToken);
$apiToken = Crypt::decryptString($token);

encryptString чи encrypt:

  • encryptString() / decryptString() - шифрує рядок як є;
  • encrypt() / decrypt() (і хелпери encrypt(), decrypt()) спершу серіалізують значення через serialize() - можна шифрувати масиви й об'єкти, але при розшифруванні викликається unserialize(). Для рядків краще encryptString.

Результат - base64 від JSON з полями iv, value, mac (чи tag для GCM). Він довший за вихідний рядок: для колонки бази потрібен text, а не короткий varchar.

Помилки розшифрування:

try {
    $value = Crypt::decryptString($payload);
} catch (DecryptException $e) {
    // значення пошкоджено, підроблено чи зашифровано іншим ключем
}

Ротація ключа. Якщо просто замінити APP_KEY, усе зашифроване старим ключем стане нечитабельним: cookie, сесії, поля з cast encrypted, збережені токени. Для плавної заміни:

APP_KEY="base64:NEW..."
APP_PREVIOUS_KEYS="base64:OLD..."
  • шифрування - завжди новим ключем;
  • розшифрування - спершу новим, потім по черзі старими з APP_PREVIOUS_KEYS;
  • користувачі не розлогінюються, дані читаються.

Але старі ключі треба колись прибрати: дані в базі, зашифровані старим ключем, лишаються такими, доки їх не перезаписати. Після ротації - команда чи задача, що читає й зберігає ці записи заново (вони перешифровуються новим ключем), і лише потім видалення старого ключа з APP_PREVIOUS_KEYS.

Що не шифрувати через Crypt:

  • паролі - їх хешують (Hash::make), а не шифрують: розшифрувати пароль неможливо має бути навіть для вас;
  • поля, за якими шукаєте: зашифроване значення щоразу різне (випадковий IV), тому where('email', ...) не спрацює. Для пошуку - окрема колонка з хешем (HMAC) значення.

Ключ - єдиний секрет усієї схеми. Витік APP_KEY разом з дампом бази - це витік усіх зашифрованих даних.

Докладніше в документації: Плавна ротація ключів шифрування

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання