Я пытаюсь понять, как проверить подписи токенов JWT с использованием .NET Framework. Я использую токен, найденный по адресу https://jwt.io/.C# Как проверить подпись на токене JWT?
Если я понимаю, как это должно работать, я могу использовать алгоритм хэширования HMACSHA256 с первыми двумя токенами и секретное значение, чтобы получить последнюю часть токена. Если это соответствует, то подпись действительна.
В примере на странице показывает https://jwt.io/ вычисления хэш следующим образом:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload), secret
)
К сожалению, объект HMACSHA256 в .NET Framework не имеет такого метода. Вы должны пройти в байт [] или поток. Также нет аргументов в пользу тайны. Существует, однако, конструктор, который берет байт [] в качестве ключа. Чтобы обойти, я преобразовал слово «secret» в байт [], создавая объект HMACSHA256 с этим.
Затем я конвертирую base64 закодированную строку header.payload в байт [] и передаю это методу ComputeHash
объекта HMACSHA256
.
Здесь я столкнулся с проблемами. Выход из ComputeHash
является байтовым массивом. Независимо от того, как я пытаюсь преобразовать этот байт [] обратно в строку, он никогда не соответствует сигнатуре. Я не понимаю, где я ошибаюсь. Является ли сигнатурная часть маркера хэш-значением или хэш-значением с кодировкой base64?
Вот мой код:
string jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
string[] parts = jwt.Split(".".ToCharArray());
string headerDotPayload = string.Format("{0}.{1}", parts[0], parts[1]);
string signature = parts[2];
byte[] secret = System.Text.UTF8Encoding.UTF8.GetBytes("secret");
byte[] input = System.Text.UTF8Encoding.UTF8.GetBytes(headerDotPayload);
var alg = new HMACSHA256(secret);
byte[] hash = alg.ComputeHash(input);
//Attempting to verify
StringBuilder result = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
result.Append(hash[i].ToString("x2"));
}
string verify1 = result.ToString(); //Does not match signature
string verify2 = System.Text.UTF8Encoding.UTF8.GetString(hash); //Does not match signature
byte[] verify3 = System.Text.UTF8Encoding.UTF8.GetBytes(signature); //Does not match value in the hash byte[]