Как вручную проверить подпись JWT с помощью онлайн-инструментов - PullRequest
0 голосов
/ 01 мая 2018

Насколько я понимаю, это простой процесс проверки подписи JWT. Но когда я использую некоторые онлайн-инструменты, чтобы сделать это для меня, это не совпадает. Как я могу вручную проверить подпись JWT без использования библиотеки JWT? Мне нужен быстрый метод (с использованием доступных онлайн-инструментов), чтобы продемонстрировать, как это делается.

Я создал свой JWT на https://jwt.io/#debugger-io со следующей информацией:

  • Алгоритм: HS256
  • Секрет: hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6
  • Заголовок:
    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • Полезная нагрузка:
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    
  • Проверка подписи (раздел):
    • Секретное значение изменено на выше
    • Закодированный секретный код base64 (независимо от того, установлен этот флажок или нет, по-прежнему получают другое значение)

JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCA

Вручную JWT попытка проверки подписи:

Использование калькулятора base64UrlEncode (http://www.simplycalc.com/base64url-encode.php или https://www.base64encode.org/)

Если я: (Не фактическое значение на сайтах, изменено, чтобы показать, что инструменты в конечном итоге создадут для меня)

base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "." + base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ")

Я получаю:

ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=

ПРИМЕЧАНИЕ: с моей стороны есть некоторая путаница, если я должен кодировать уже закодированные значения или использовать уже закодированные значения как есть.

(т. Е. С использованием base64UrlEncode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9") + "." + base64UrlEncode("eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ") против "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ").

Независимо от того, на котором я должен сделать, конечный результат все еще не соответствует подписи. Я склоняюсь к тому, что мне следует НЕ перекодировать закодированное значение, правда это или нет.

Затем с помощью калькулятора HMAC Generator (https://codebeautify.org/hmac-generator или https://www.freeformatter.com/hmac-generator.html#ad-output)

(Не фактическое значение на сайтах, изменено, чтобы показать, что инструменты в конечном итоге создадут для меня)

HMACSHA256(
 "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5.ZXlKemRXSWlPaUl4TWpNME5UWTNPRGt3SWl3aWJtRnRaU0k2SWtwdmFHNGdSRzlsSWl3aWFXRjBJam94TlRFMk1qTTVNREl5ZlE=",
  "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6"
)

Что меня достает:

a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01

И это не соответствует сигнатурной части JWT:

wDQ2mU5n89f2HsHm1dluHGNebbXeNr748yJ9kUNDNCAM ! = a2de322575675ba19ec272e83634755d4c3c2cd74e9e23c8e4c45e1683536e01


Назначение:

Причина, по которой мне нужно это подтвердить, состоит в том, чтобы доказать способность подтвердить, что JWT не был подделан, без расшифровки JWT.

Моему клиентскому веб-интерфейсу не нужно декодировать JWT, поэтому им не нужно устанавливать jwt пакет для этого. Им просто нужно сделать простую проверку, чтобы подтвердить, что JWT не был подделан (хотя это маловероятно), прежде чем они сохранят JWT для будущих вызовов API.

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

У меня была такая же проблема, пока я не понял, что вместо base64url я использую обычную кодировку base64. Есть также некоторые мелкие детали между ними. Вот пошаговое руководство, которое, надеюсь, сделает весь процесс намного более понятным.

Примечания

Примечание 1: Вы должны удалить все пробелы и символы новой строки из строк JSON (заголовок и полезная нагрузка). Это неявно делается на jwt.io , когда вы генерируете токен JWT.

Примечание 2: Для преобразования строки JSON в строку base64url на cryptii.com создайте следующую конфигурацию:

First view: Text

Second view: Encode
    Encoding: Base64
    Variant: Standard 'base64url' (RFC 4648 §5)

Third view: Text

Примечание 3: Для преобразования HMAC-кода HEX (подпись) в строку base64url на cryptii.com создайте следующую конфигурацию:

First view: Bytes
    Format: Hexadecimal
    Group by: None

Second view: Encode
    Encoding: Base64
    Variant: Standard 'base64url' (RFC 4648 §5)

Third view: Text

Руководство

Вам понадобятся только два онлайн-инструмента:

  1. [Инструмент 1]: cryptii.com - для кодирования base64url,
  2. [Инструмент 2]: codebeautify.org - для расчета HMAC.

На cryptii.com вы можете выполнять как base64url кодирование / декодирование, так и вычисление HMAC, но для HMAC вам необходимо предоставить ключ HEX, который отличается от ввода на jwt. IO , поэтому я использовал отдельный сервис для расчета HMAC.

Входные данные

В этом руководстве я использовал следующие данные:

  • Заголовок:

    {"alg":"HS256","typ":"JWT"}
    
  • Полезная нагрузка:

    {"sub":"1234567890","name":"John Doe","iat":1516239022}
    
  • Секрет (ключ):

    The Earth is flat!
    

Секрет не закодирован base64.

Шаг 1: Преобразовать заголовок [Инструмент 1]

  • Заголовок (простой текст):

    {"alg":"HS256","typ":"JWT"}
    
  • Заголовок (base64url кодированный):

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    

Шаг 2. Преобразование полезной нагрузки [Инструмент 1]

  • Полезная нагрузка (простой текст):

    {"sub":"1234567890","name":"John Doe","iat":1516239022}
    
  • Полезная нагрузка (base64url кодированная):

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    

Шаг 3: Рассчитать код HMAC (подпись) [Инструмент 2]

Расчет HMAC с использованием алгоритма SHA256.

  • Входная строка (base64url кодированный заголовок и полезная нагрузка, соединенные точкой):

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
  • Расчетный код (шестнадцатеричный номер):

    c8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352
    

Рассчитанный код HMAC является шестнадцатеричным представлением подписи. Примечание: его следует кодировать не base64url в виде простой текстовой строки, а в виде последовательности байтов.

Шаг 4: закодировать вычисленный код HMAC в base64url [Инструмент 1]:

  • Подпись (в байтах):

    c8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352
    
  • Подпись (base64url в кодировке):

    yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I
    

Резюме

Вот наши результаты (все base64url в кодировке):

  • Заголовок:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    
  • Полезная нагрузка:

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
  • Подпись:

    yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I
    

Результаты jwt.io :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I

Как видите, все три части идентичны.

0 голосов
/ 03 мая 2018

Все дело в форматах и ​​кодировке.

Вкл. https://jwt.io вы получаете этот токен, основываясь на ваших входных значениях и секрете:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

Мы хотим доказать, что подпись:

3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

правильно.

Подпись - это хеш HMAC-SHA256, закодированный в Base64url. (как описано в RFC7515 )

При использовании онлайн-генератора HMAC для вычисления хеша для

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

с секретом

hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6

вы получите

de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3

как результат, который является значением HMAC-SHA256, но не закодирован Base64url. Этот хэш представляет собой шестнадцатеричное строковое представление большого числа.

Чтобы сравнить его со значением из https://jwt.io, вам необходимо преобразовать значение из его шестнадцатеричного строкового представления обратно в число, а Base64url закодировать его.

Следующий скрипт делает это, а также использует crypto-js для вычисления собственного хэша. Это также может быть способом проверки без библиотек JWT.

var CryptoJS = require("crypto-js");

// the input values
var base64Header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
var base64Payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ";
var secret = "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6";

// two hashes from different online tools
var signatureJWTIO = "3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M";
var onlineCaluclatedHS256 =  "de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3";

// hash calculation with Crypto-JS. 
// The two replace expressions convert Base64 to Base64url format by replacing '+' with '-' 
// and stripping the '=' padding
var base64Signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , secret).toString(CryptoJS.enc.Base64).replace(/\+/g,'-').replace(/\=+$/m,'');

// converting the online calculated value to Base64 representation
var base64hash = new Buffer(onlineCaluclatedHS256, 'hex').toString('base64').replace(/\+/g,'-').replace(/\=+$/m,'');


// the results:
console.log("Signature from JWT.IO             : " + signatureJWTIO);
console.log("NodeJS calculated hash            : " + base64Signature);
console.log("online calulated hash (converted) : " + base64hash);

Результаты:

Signature from JWT.IO             : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

NodeJS calculated hash            : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

online calulated hash (converted) : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

идентичны!

Вывод:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...