Декодирование токена JWT даже при изменении последнего символа подписи - PullRequest
2 голосов
/ 21 октября 2019

Я просто попробовать JWT маркеры на рельсы приложение, с помощью этой библиотеки JWT: https://github.com/jwt/ruby-jwt

JWT.encode({sss: "333"}, 'SECRET_KEY')

возвращает ниже маркер:

eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HA

Затем я расшифровал, используя вышеуказанный токен

JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HA", 'SECRET_KEY')

, верный ответ ниже правильно:

[{"sss" => "333"}, {"alg" => "HS256"}]

Но если я попытаюсь изменить последнюю букву токена на B вместо текущей A он по-прежнему возвращает тот же самый ответ, что странно.

JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HB", 'SECRET_KEY')

Получение этого ответа, даже если предоставленный мной токен неверен:

[{"sss" => "333 "}, {" alg "=>" HS256 "}]

На самом деле я получаю одинаковый ответ для всех символов до 'D'

Если я использую F и другие выше, чем это показывает ошибка, как и ожидалось:

JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HF", 'SECRET_KEY')

JWT :: VerificationError (проверка подписи поднята) от (irb): 34

Что можетбыть причиной этого? Это ожидаемое поведение или я здесь что-то не так делаю?

1 Ответ

1 голос
/ 22 октября 2019

Причина в кодировке base64url. Все три части JWT все закодированы в base64url. Кодировка Base64 преобразует входные данные в 6-битное представление, сопоставленное с набором из 64 символов ASCII. Если у вас есть 3-байтовые исходные данные, результат, закодированный в base64, имеет длину 4 символа, каждый символ представляет 6-битное значение, поэтому 4 * 6 бит = 24 бита.

В вашем случае кодированная подпись имеет 43 символа, что означает 43 * 6 = 258 бит. Таким образом, теоретически можно кодировать 258 бит, но длина сигнатуры составляет всего 256 бит (32 байта), что означает, что на конце имеется 2 незначительных бита.

Взгляд на таблицу кодирования base64 показывает, что от 'A' до 'D' представляют 6-битные значения от 0 (000000) до 4 (000011), поэтому первые четыре бита, которые все еще значимы, все идентичны, и изменяются только последние два несущественных бита,Но символ «Е» означает 5 (000100) и изменит последний бит 256-битного значения.

Вывод: все в порядке, здесь все в порядке, все работает, как и ожидалось.

...