LWT
LWT — собственный трёхсегментный формат LWTv3 для JSON-данных с подписью и необязательным шифрованием payload. Класс localzet\LWT предоставляет статические encode() и decode().
Форма header.payload.signature похожа на JWT, но заголовки, encrypted payload и некоторые способы формирования подписи отличаются. Обычный JWT/JWE-потребитель не становится совместимым с LWT автоматически.
Подключение
Заголовок раздела «Подключение»Манифест требует PHP 7.4+, OpenSSL, mbstring и JSON; для EdDSA дополнительно нужен sodium.
composer config repositories.localzet-lwt vcs https://github.com/localzet/LWTcomposer require localzet/lwt:dev-mainПодписанные открытые данные
Заголовок раздела «Подписанные открытые данные»Для HMAC без дополнительного шифрования:
use localzet\LWT;
$key = random_bytes(32);$token = LWT::encode(['sub' => 'user:42'], $key, 'HS256');$payload = LWT::decode($token, $key, 'HS256');Ключ нужно сохранять между запросами; случайный ключ здесь служит только для самостоятельного примера. Payload в этом режиме — JSON в base64url и доступен любому получателю токена. Подпись не обеспечивает конфиденциальность.
Передавайте алгоритм из доверенной конфигурации, не из непроверенного заголовка. Для HMAC используйте секретные случайные байты, а не публичный PEM. У LWT нет той же строгой проверки типа/минимальной длины HMAC-ключа, которая реализована в соседней библиотеке JWT.
Шифрование payload
Заголовок раздела «Шифрование payload»Четвёртый аргумент включает дополнительный слой шифрования:
$token = LWT::encode($data, $signingPrivateKey, 'RS256', $recipientPublicRsaKey);$payload = LWT::decode($token, $signingPublicKey, 'RS256', $recipientPrivateRsaKey);Данные кодируются в JSON, шифруются случайным 32-байтовым AES-ключом с AES-256-CBC и случайным IV. AES-ключ оборачивается RSA. Для обычного направления отправитель использует публичный ключ получателя, получатель — свой приватный ключ. Ключ подписи и ключ шифрования имеют разные назначения.
Заголовок остаётся открытым. Включение шифрования меняет cty с JWS на LZX и добавляет enc = AES-256-CBC+RSA. Это собственный envelope, не пятисегментный стандартный JWE.
decode() сначала проверяет header, затем разбирает/расшифровывает payload и только после этого проверяет подпись. Поэтому он не является интерфейсом «проверить подлинность до любой обработки зашифрованного тела». Не открывайте такую обработку произвольному недоверенному трафику без отдельного анализа границы доверия и ограничений входа.
Claims и авторизация
Заголовок раздела «Claims и авторизация»LWT возвращает данные после проверки подписи, но не проверяет exp, nbf, iat, issuer, audience и назначение токена. Токен с прошедшей подписью и просроченным exp сам по себе не будет отклонён.
В прикладном verifier должны быть явные проверки срока, issuer/audience, обязательных полей и права на операцию. У формата нет встроенного revocation store, защиты от повторного использования или связывания с сессией.
Совместимость алгоритмов
Заголовок раздела «Совместимость алгоритмов»Реализация перечисляет HMAC, RSA PKCS#1, ECDSA и EdDSA, а также старые SHA-1-варианты, ES256K и HS256/64. Перечисление не означает, что каждый вариант даёт совместимый или успешно проверяемый токен.
В частности, HS256/64 обрезает подпись при выпуске до восьми байт, а проверка сравнивает её с полным HMAC. ECDSA использует подпись OpenSSL DER без преобразования в JOSE R||S. Не передавайте такой токен стандартному JWT verifier в расчёте на одинаковую строку alg.
Для интеграции используйте явно выбранный и проверенный профиль; не объявляйте поддержку всех перечисленных строк алгоритмов на основании allowlist.
Исходный код · AGPL-3.0