Расшифровка JWT HS256 и сверка сигнатуры sha256

JWT (JSON Web Token) имеет три компонента, разделенных точками: заголовок, полезная нагрузка (payload) и подпись. Подпись представляет собой шифрованный хэш от первых двух компонентов, используя ключ.

При создании токена сервер формирует заголовок и полезную нагрузку, записывает их в формат JSON и кодирует в измененный BASE64. Это дает две строки, которые объединяются через точку. Затем формируется подпись от общей строки с использованием указанного в заголовке алгоритма. Подпись добавляется через точку, создавая полный токен.

При получении запроса с токеном сервер разбивает токен на компоненты, расшифровывает заголовок и определяет алгоритм подписи. Затем сервер вычисляет контрольную подпись от первых двух компонентов токена и сравнивает ее с той, что указана в токене. Если они совпадают, токен считается действительным.

При использовании симметричного алгоритма оба сервера знают один и тот же ключ - сервер, который генерирует токен, и сервер, который его проверяет. Асимметричное шифрование позволяет создавать токены на одном сервере с использованием закрытого ключа и проверять их на другом сервере с использованием соответствующего открытого ключа.

Пример токена:

$token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.qeDJnxS97205riRwowv_szvCv-h2IiPqAAnhFA214CI';

Секретный ключ которым был зашифрован:

$key = 'private_key';

Рассмотрим обработку и сверку сигнатур:

<?php
$token = 'Приведен выше';
$key = 'Приведен выше';

// Разделяем наш token на 3 переменные
$jwtArr = array_combine(['header', 'payload', 'signature'], explode('.', $token));

// base64_decode($jwtArr['header']) - заголовок
// {"alg":"HS256","typ":"JWT"}
//
// base64_decode($jwtArr['payload']) - тело
// {"alg":"HS256","typ":"JWT"}
//
// $jwtArr['signature'] - подпись на основе секретного ключа, $key
// qeDJnxS97205riRwowv_szvCv-h2IiPqAAnhFA214CI

$calculatedHash = hash_hmac(
        'sha256',
        $jwtArr['header'] . '.' . $jwtArr['payload'],
        $key,
        true);

// sha256 сумму, кодируем в base64 и приводим к полной версии
$calcSign = convertBase64UrlToBase64(base64_encode($calculatedHash));

// Приводим к полной версии сигнатуру, которая была в коде
$unswerS = convertBase64UrlToBase64($jwtArr['signature']);

if ($calcSign === $unswerS) {
    die("Сигнатура совпала, целостность не нарушена");
} else {
    die("Сигнатура НЕ совпала, целостность НАРУШЕНА");
}

// Приводит обрезанную base64 в нормальную
function convertBase64UrlToBase64($input) {
    $remainder = \strlen($input) % 4;
    if ($remainder) {
        $padlen = 4 - $remainder;
        $input .= \str_repeat('=', $padlen);
    }
    return \strtr($input, '-_', '+/');
}

Путем вычисления SHA-256 хэша для объединенных первых двух частей токена с применением соответствующего ключа можно удостовериться, что этот хэш совпадает с первой частью токена, что подтверждает отсутствие изменений в первых двух частях.

Сервис для онлайн кодирования jwt для тестов.

Библиотека с готовыми решениями firebase/php-jwt

Источник

1234 0

Комментарии

Пока нет ни одного отзыва. Оставьте отзыв первым
Только авторизованные пользователи могут оставлять комментарии Вход

Похожие статьи

Создать и скачать CSV на PHP

Рассмотрим возможность быстрого создания CSV файла с автоматическим скачиванием файла. Рассмотрим формирование, разделители и header для возможности скачать файл.

Долгое хранение корзины в интернет-магазине

Рассмотрим варианты популярные варианты хранения товаров в корзине в интернет-магазине. Обозначим плюсы и минусы таких хранений. Рассмотрим варианты долгосрочного хранения корзины.