Я использую PHP Firebase JWT для реализации JWT в своем PHP-приложении. Вот мой код
$payload = [
'iss' => 'http://test.com',
'aud' => 'http://test.com',
'iat' => time(), // Issued at
'exp' => time() + 3600, // Expiration (1 hour)
'data' => [
'user_id' => $user['id'],
'email' => $user['email'],
'role' => $user['role'],
'is_admin' => $user['isadmin']
]
];
$jwt = JWT::encode($payload, $key, 'HS256', $key_file);
После кодирования генерирует токен eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6Ii92YXIvd3d3L215a2V5LmtleSJ9.eyJpc3MiOiJodHRwOi8vdGVzdC5jb20iLCJhdWQiOiJodHRwOi8vdGVzdC5jb20iLCJpYXQiOjE3MjM5NzQ5OTMsImV4cCI6MTcyMzk3ODU5MywiZGF0YSI6eyJ1c2VyX2lkIjoxLCJlbWFpbCI6ImFiYyIsInJvbGUiOiJ1c2VyIiwiaXNfYWRtaW4iOjB9fQ.uC13pivSZGnPr6i8zmPCfEFMsykWR5miIK8t0-DCnug
это нормально
Содержимое ключевого файла: hellohellohellohellohellohellohe
Я использовал сайт https://jwt.io/ для тестирования своего токена и несколько других сайтов https://dinochiesa.github.io/jwt/
Теперь я хочу, чтобы обычный пользователь сгенерировал токен через любой веб-сайт, изменив ключевой параметр kid и используя любой веб-сайт в Интернете, чтобы его можно было использовать на сайте (демонстрируя уязвимость).
Я столкнулся с двумя проблемами; если я попытаюсь проверить токен с помощью вышеуказанного ключа на любом из веб-сайтов с файлом ключа, он скажет, что он не может сопоставиться или проверить; в чем проблема? Работает ли JWT на основе PHP Firebase по-другому? Я тоже проверил это Подпись JWT не проверяется в PHP
🤔 А знаете ли вы, что...
С PHP можно создавать динамические веб-сайты и веб-приложения.
Поскольку вы читаете ключ из файла, а не тестируете его с жестко закодированным значением, трудно увидеть, есть ли в нем дополнительные символы, например, разрывы строк.
Если вы сгенерируете хэш вручную, используя то, что, по вашему мнению, является вашим ключом, вы увидите другую подпись:
$msg = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6Ii92YXIvd3d3L215a2V5LmtleSJ9.eyJpc3MiOiJodHRwOi8vdGVzdC5jb20iLCJhdWQiOiJodHRwOi8vdGVzdC5jb20iLCJpYXQiOjE3MjM5NzQ5OTMsImV4cCI6MTcyMzk3ODU5MywiZGF0YSI6eyJ1c2VyX2lkIjoxLCJlbWFpbCI6ImFiYyIsInJvbGUiOiJ1c2VyIiwiaXNfYWRtaW4iOjB9fQ';
$key = 'hellohellohellohellohellohellohe';
$algorithm = 'SHA256';
$signature = hash_hmac($algorithm, $msg, $key, true);
echo base64_encode($signature);
#=> zBeba1d7bk/OhMeo5P/Aw1aO2v4JxW+8QXGJsCx1AWI=
Но если вы добавите одну новую строку в конце, вы увидите подпись в образце JWT (кроме немного другого варианта кодировки BASE64 с «-» вместо «+»):
$msg = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6Ii92YXIvd3d3L215a2V5LmtleSJ9.eyJpc3MiOiJodHRwOi8vdGVzdC5jb20iLCJhdWQiOiJodHRwOi8vdGVzdC5jb20iLCJpYXQiOjE3MjM5NzQ5OTMsImV4cCI6MTcyMzk3ODU5MywiZGF0YSI6eyJ1c2VyX2lkIjoxLCJlbWFpbCI6ImFiYyIsInJvbGUiOiJ1c2VyIiwiaXNfYWRtaW4iOjB9fQ';
$key = "hellohellohellohellohellohellohe\n";
$algorithm = 'SHA256';
$signature = hash_hmac($algorithm, $msg, $key, true);
echo base64_encode($signature);
#=> uC13pivSZGnPr6i8zmPCfEFMsykWR5miIK8t0+DCnug=
Вы могли бы провести тот же эксперимент непосредственно с функцией JWT::encode
, но у меня нет под рукой среды, в которой я мог бы установить библиотеку.