#c# #jwt #ecdsa #jwk
#c# #jwt #ecdsa #jwk
Вопрос:
У меня есть веб-страница, отображаемая на сайте поставщика в iframe. Они вызывают мою страницу и передают JWT в строке запроса. Я должен разобрать jwt.
eyJraWQiOiIyMDIwLTA5LTAyVDE3OjM2OjE3LjU3MC5lYyIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJ1cm46Y2VybmVyOmlkZW50aXR5LWZlZGVyYXRpb246cmVhbG06SFdPb0lsUlgyWWRGZjkyNGJBZTZSR0l5WmtuajZrTjctY2g6cHJpbmNpcGFsOnRhNDh6OWdkNTVkNndyNW0iLCJhdWQiOiJodHRwczpcL1wvdXJsMjU4dmowai5leGVjdXRlLWFwaS51cy1lYXN0LTIuYW1hem9uYXdzLmNvbSIsImlzcyI6Imh0dHBzOlwvXC9kZXYuYmF5Y2FyZS5wYXRpZW50cG9ydGFsLnVzLTEuaGVhbHRoZWludGVudC5jb20iLCJleHAiOjE1OTkxNTQ1MTYsImlhdCI6MTU5OTE1MzkxNiwic2lkIjoiZGUwNmJhNmUtYjQyYy00ZmY5LWI4MmQtYmM4NjY0ODJmODU4In0.6Ru5Lyd1Zq016uv84pP-GjSuz6koVNipa_cd939eF21-5N2_A0Nj3I6AkDhuHrE870WzyTiCmZfkIjMOFZkRCA
Я предполагаю проверить подпись, извлекая значения изhttps://authorizion.x.com/jwk . Я получаю значения, которые выглядят примерно так:
{
"keys":[
{
"kty":"EC",
"crv":"P-256",
"kid":"2020-09-04T18:16:04.934.ec",
"x":"82WEbXbnfGC1kmMfjJch6gFJRp7hEp08gzZQdBLLFIk",
"y":"ytkPwl4IjLw8M94DzgTmdAbxjq0AmmYu9mMmxpU3eBI"
},
{
"kty":"EC",
"crv":"P-256",
"kid":"2020-09-02T17:36:17.570.ec",
"x":"uAfEPKELRuUVMtB0DCB5oyYWnfiV8-9zHYntvI0lsRE",
"y":"32J6nVgeb9RLdWK21QNDHhWdOsZJbxvyEq2n0IOvLtQ"
},
{
"kty":"EC",
"crv":"P-256",
"kid":"2020-08-31T17:36:17.359.ec",
"x":"HsxFY2vihycZgYnkSTLDHJ0Cagr2nUcZTbf2yQKPS6A",
"y":"4kLClPGM0TG_gCUlBKkYdXrlLFVasPxQ2UOvwSBKyt0"
}
]
}
Я выбираю ключ на основе значения kid в заголовке JWT. Как мне проверить подпись на основе значений crv, x и y ? Похоже, мне нужен либо публичный, либо закрытый сертификат, но у меня его нет.
Что еще я могу добавить. Он использует шифрование ECDSA p-256. Существует веб-токен Json выше и на jwt.io Я получаю следующие значения,
Заголовок
{
"kid": "2020-09-02T17:36:17.570.ec",
"typ": "JWT",
"alg": "ES256"
}
Полезная нагрузка
{
"sub": "urn:cerner:identity-federation:realm:HWOoIlRX2YdFf924bAe6RGIyZknj6kN7-ch:principal:ta48z9gd55d6wr5m",
"aud": "https://url258vj0j.execute-api.us-east-2.amazonaws.com",
"iss": "https://dev.baycare.patientportal.us-1.healtheintent.com",
"exp": 1599154516,
"iat": 1599153916,
"sid": "de06ba6e-b42c-4ff9-b82d-bc866482f858"
}
Подпись
6Ru5Lyd1Zq016uv84pP-GjSuz6koVNipa_cd939eF21-5N2_A0Nj3I6AkDhuHrE870WzyTiCmZfkIjMOFZkRCA
Я включил набор веб-ключей Java, соответствующий JWT.
Ответ №1:
Вот очень короткое решение, основанное на Jose.
В основном вам нужно прочитать JWK с заданного URL, выбрать правильный JWK с соответствующим идентификатором ключа ( kid
), создать ECJWKey
на основе заданных параметров в кодировке Base64 x
и y
, а затем проверить JWT с помощью этого ключа:
Следующий исходный код является лишь краткой иллюстрацией процесса, а ключ жестко закодирован и не считывается с конечной точки JWKS.
using Jose;
using System;
using System.Security.Cryptography;
namespace JWKValiadation
{
public class ECJWKey
{
public string kty { get; set; }
public string crv { get; set; }
public string kid { get; set; }
public string x { get; set; }
public string y { get; set; }
}
class Program
{
static void Main(string[] args)
{
ECJWKey ecjwkkey = new ECJWKey
{
kty = "EC",
crv = "P-256",
kid = "2020-09-02T17:36:17.570.ec",
x = "uAfEPKELRuUVMtB0DCB5oyYWnfiV8-9zHYntvI0lsRE",
y = "32J6nVgeb9RLdWK21QNDHhWdOsZJbxvyEq2n0IOvLtQ"
};
string tokenEC = "eyJraWQiOiIyMDIwLTA5LTAyVDE3OjM2OjE3LjU3MC5lYyIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJ1cm46Y2VybmVyOmlkZW50aXR5LWZlZGVyYXRpb246cmVhbG06SFdPb0lsUlgyWWRGZjkyNGJBZTZSR0l5WmtuajZrTjctY2g6cHJpbmNpcGFsOnRhNDh6OWdkNTVkNndyNW0iLCJhdWQiOiJodHRwczpcL1wvdXJsMjU4dmowai5leGVjdXRlLWFwaS51cy1lYXN0LTIuYW1hem9uYXdzLmNvbSIsImlzcyI6Imh0dHBzOlwvXC9kZXYuYmF5Y2FyZS5wYXRpZW50cG9ydGFsLnVzLTEuaGVhbHRoZWludGVudC5jb20iLCJleHAiOjE1OTkxNTQ1MTYsImlhdCI6MTU5OTE1MzkxNiwic2lkIjoiZGUwNmJhNmUtYjQyYy00ZmY5LWI4MmQtYmM4NjY0ODJmODU4In0.6Ru5Lyd1Zq016uv84pP-GjSuz6koVNipa_cd939eF21-5N2_A0Nj3I6AkDhuHrE870WzyTiCmZfkIjMOFZkRCA";
// first read the header to get the kid
var headers = Jose.JWT.Headers(tokenEC);
if(headers.TryGetValue("kid", out var keyId))
{
// in a real application you would need the kid
// to select the right key from the JKWS
Console.WriteLine(keyId);
}
// create the key based on the parameters from the JWK
ECDsa eckey = ECDsa.Create(new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = Base64Url.Decode(ecjwkkey.x),
Y = Base64Url.Decode(ecjwkkey.y)
}
});
// verify and decode the token
string payload = Jose.JWT.Decode(tokenEC, eckey);
Console.WriteLine(payload);
}
}
}
Комментарии:
1. Потрясающе. Краткий и понятный рабочий пример. Я надеюсь, что это поможет другим в будущем! Спасибо. Я кодировал до базы 64, а не декодировал. Теперь все лучше.