AEGIS у PHP 8.4: як увімкнути та безпечно використати швидке AEAD‑шифрування

У статті розбирається підхід Ayesh Karunaratne до використання AEGIS у PHP через розширення Sodium: коли алгоритми доступні, чим відрізняються AEGIS-128L і AEGIS-256 та як їх застосувати на практиці.

Коли AEGIS реально доступний у вашому PHP

AEGIS вбудовано не у всі збірки PHP. Щоб функції AEGIS працювали, потрібні одночасно три умови:

  • версія PHP 8.4 або новіша
  • розширення Sodium зібране з libsodium версії 1.0.19 або новішої
  • процесорна архітектура x86_64 або aarch64 (64-бітні CPU, які мають апаратне прискорення AES)

Практичний спосіб перевірити доступність AEGIS — не дивитися на версії, а перевірити наявність конкретної функції Sodium. Наприклад:

if (function_exists('\sodium_crypto_aead_aegis128l_encrypt')) {
    // AEGIS available
}

Якщо ця перевірка повертає true, можна спиратися на AEGIS-128L і AEGIS-256. Якщо ні — доведеться залишитися на AES-GCM або CHACHA20-POLY1305.

Що таке AEGIS в контексті PHP Sodium

AEGIS — це сімейство AEAD-алгоритмів (authenticated encryption with associated data) на основі AES. У PHP через Sodium доступні дві реалізації:

  • AEGIS-128L — ключ 128 біт, nonce 128 біт
  • AEGIS-256 — ключ 256 біт, nonce 256 біт

Обидва алгоритми:

  • шифрують повідомлення з автентифікацією (перевіряють цілісність і ключ)
  • дозволяють додаткові дані (AAD), які не шифруються, але включаються в MAC (наприклад, ID користувача)
  • теоретично підтримують довжини даних менше ніж 2^64 біт

Важливий нюанс: у Sodium більшість AEAD-алгоритмів використовує 256-бітні ключі. AEGIS-128L — єдиний варіант з 128-бітним ключем, тож не варто намагатися «перевикористати» ключі від інших алгоритмів без явної регенерації.

Оригінальна робота про AEGIS описує внутрішню конструкцію алгоритмів; Ayesh Karunaratne посилається на неї як на джерело теорії.

AEGIS-128L: приклад використання та практичні акценти

AEGIS-128L у PHP зручно використовувати для типових задач симетричного шифрування (наприклад, захист токенів або локально зашифрованих даних користувача). Схема роботи така:

  1. Генеруємо випадковий ключ довжини 16 байт функцією Sodium
  2. Генеруємо випадковий nonce фіксованої довжини (16 байт)
  3. Визначаємо додаткові дані (AAD) — вони можуть бути порожніми
  4. Шифруємо повідомлення
  5. Для розшифрування використовуємо ті ж ключ, nonce і AAD

У PHP це виглядає так:

// generate a random key of sufficient length (16 bytes)
// This value must not be public.
$key = sodium_crypto_aead_aegis128l_keygen();

// Generate random nonce value of SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES length (16 bytes).
// This value should be stored along the encrypted text, but is not required to be private
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES);

// Additional data. This can be a user ID, email address, or empty.
$additional_data = '';

// Message to encrypt
$message = 'Hello';

// Encrypt
$ciphertext = sodium_crypto_aead_aegis128l_encrypt($message, $additional_data, $nonce, $key);
// Decrypt
$decryptedMessage = sodium_crypto_aead_aegis128l_decrypt($ciphertext, $additional_data, $nonce, $key); // "Hello"

Кілька практичних моментів на основі прикладу:

  • Ключ має залишатися конфіденційним. У продакшні його варто зберігати поза репозиторієм коду: в системі керування секретами, в змінних середовища або окремому захищеному сховищі.
  • Nonce не обов'язково тримати в секреті, але його необхідно зберегти разом із шифртекстом, щоб потім розшифрувати дані.
  • З точки зору безпеки для AEAD-алгоритмів критично не повторювати одну й ту ж пару «ключ + nonce» для різних повідомлень. У прикладі показане випадкове генерування nonce, що підходить для більшості сценаріїв, якщо генератор випадкових чисел криптографічно стійкий.
  • Additional data можна використовувати як «прив'язку» шифрування до певного контексту, наприклад до конкретного користувача. Якщо під час дешифрування AAD змінити, функція поверне false.

AEGIS-256: коли обрати старшого «брата»

AEGIS-256 працює аналогічно, але з ширшим ключем та nonce:

  • довжина ключа 32 байти (256 біт)
  • довжина nonce задається константою SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES (32 байти)
  • допускає ті ж обмеження на загальну довжину даних, що й AEGIS-128L (менше 2^64 біт)

Автор зазначає, що AEGIS-256 зазвичай приблизно на 20 % більш обчислювально затратний, ніж AEGIS-128L, якщо не брати до уваги окремі винятки.

Приклад використання виглядає практично так само, як і для AEGIS-128L, але з іншими функціями та константами:

// generate a random key of sufficient length (32 bytes)
// This value must not be public.
$key = sodium_crypto_aead_aegis256_keygen();

// Generate random nonce value of SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES length (32 bytes).
// This value should be stored along the encrypted text, but is not required to be private
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES);

// Additional data. This can be a user ID, email address, or empty.
$additional_data = '';

// Message to encrypt
$message = 'Hello';

// Encrypt
$ciphertext = sodium_crypto_aead_aegis256_encrypt($message, $additional_data, $nonce, $key);
// Decrypt
$decryptedMessage = sodium_crypto_aead_aegis256_decrypt($ciphertext, $additional_data, $nonce, $key); // "Hello"

З погляду дизайну API це означає:

  • можна легко «підмінити» алгоритм в існуючій системі, де вже використовується інший AEAD з Sodium: структура викликів і наявність AAD такі ж
  • варто зберігати разом із шифртекстом і nonce ще й ідентифікатор алгоритму, щоб мати змогу надалі міняти алгоритм шифрування без зламу формату даних

Перформанс: де саме AEGIS дає виграш

Ayesh Karunaratne наводить результати бенчмарків AEGIS проти AES-GCM та CHACHA20-POLY1305 на процесорі AMD Ryzen 4800H (x86_64 з AES-NI). Тести охоплюють два сценарії:

  • Data rate — шифрування блоку 20 МБ випадкових даних, середнє з 100 ітерацій (без урахування часу генерації ключів і nonce)
  • Operations/second — шифрування 1 КБ даних, середнє з 1 000 000 ітерацій (також без RNG-частини)

Зведені результати:

Algorithm Data Rate (GB/sec) Operations/sec
aes256gcm 2.31 GB/sec 1,168,300 ops/sec
chacha20poly1305 1.29 GB/sec 738,411 ops/sec
chacha20poly1305_ietf 1.28 GB/sec 746,409 ops/sec
xchacha20poly1305 1.28 GB/sec 692,764 ops/sec
aegis128l 4.99 GB/sec 1,925,310 ops/sec
aegis256 4.61 GB/sec 1,771,924 ops/sec

З цих цифр випливають кілька практичних висновків саме в рамках наведеного тесту:

  • AEGIS-128L приблизно удвічі швидший за AES-GCM за пропускною здатністю (4.99 проти 2.31 GB/сек)
  • AEGIS-256 дещо повільніший за AEGIS-128L, але все одно помітно швидший за AES-GCM
  • обидва варіанти AEGIS у кілька разів випереджають CHACHA20-POLY1305 у цих умовах
  • AEGIS-алгоритми виконують більш ніж удвічі більше операцій шифрування 1 КБ за секунду порівняно з AES-GCM

Автор окремо наголошує на контексті: усі AES-алгоритми (включно з AEGIS) на процесорах з підтримкою AES-NI працюють значно швидше. Натомість на слабких мобільних та вбудованих пристроях, які не мають AES-NI, перевага може бути іншою. Більшість серверів, на яких запускають PHP, близькі до умов бенчмарків або здатні досягати подібних швидкостей.

Як інтегрувати AEGIS у існуючий PHP-проєкт

Окремо від синтаксису функцій, зручно врахувати таку практичну схему:

  1. На старті додатку перевірити, чи доступний AEGIS (як у прикладі з function_exists).
  2. Якщо AEGIS є, обрати базовим алгоритмом AEGIS-128L або AEGIS-256 (залежно від політики безпеки та вимог до швидкості).
  3. У форматі збереження шифртексту додати поле «algorithm», щоб підтримати подальшу міграцію.
  4. Організувати централізований сервіс шифрування, який ховає від бізнес-логіки деталі ключів, nonce та вибору алгоритму.

Підхід, описаний Ayesh Karunaratne, дає зрозумілий базовий шаблон для роботи з AEGIS у PHP 8.4: окремі функції для кожного алгоритму, явна робота з nonce та додатковими даними й можливість отримати суттєвий виграш у швидкості на сучасних серверних CPU.

Ілюстрації з оригіналу

AEGIS Encryption with PHP Sodium Extension


Джерело: Ayesh Karunaratne — PHP.Watch: статьи

Пошук

Закрити