Как проверить JWT с помощью JWK для ES256 alg? - PullRequest
2 голосов
/ 07 августа 2020

У меня JWT как

var signedJwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6IjZjNTUxNmUxLTkyZGMtNDc5ZS1hOGZmLTVhNTE5OTJlMDAwMSIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1OTY3MzA4ODMsInJlcXVlc3RfYm9keV9zaGEyNTYiOiI4NDMyODhkMWMxYmM0NzhlMTBhOTM2NWQ1YjIzY2U5ZWZlY2E2ZjdkYjA3NDQ3Y2JmNjU4YTg3ZjEzZjI1ZjJmIn0.3yQY6gtNq0lQlx6eNLO_3coGqf2VkX2CBRWam9Lz0dcVvr8h4LkYfuZMwQf1fzZ_XXHEV_o17LciyBC-O72UUw"

, затем я получил ключ publi c как:

{
    "alg": "ES256",
    "created_at": 1560466143,
    "crv": "P-256",
    "expired_at": null,
    "kid": "6c5516e1-92dc-479e-a8ff-5a51992e0001",
    "kty": "EC",
    "use": "sig",
    "x": "35lvC8uz2QrWpQJ3TUH8t9o9DURMp7ydU518RKDl20k",
    "y": "I8BuXB2bvxelzJAd7OKhd-ZwjCst05Fx47Mb_0ugros"
}

Я пытаюсь декодировать с помощью библиотеки Jose в C#

var claims = Jose.JWT.Decode(signedJwt, publicKey, JwsAlgorithm.ES256);

Каждый раз, когда я получаю сообщение об ошибке:

Алгоритм EcdsaUsingSha ожидает, что ключ будет типа CngKey или ECDsa.

Я предполагаю, что я использование ключа неверно, но я не смог найти способ преобразовать ключ json в pem или что-то еще.

1 Ответ

2 голосов
/ 07 августа 2020

Вы можете создать ключ типа EccKey из JWK следующим образом:

using Jose;
using Microsoft.AspNetCore.WebUtilities;
using Security.Cryptography;
using System;
using System.Text.Json;

namespace josejwttest
{
    public class JWK
    {
        public string alg { get; set; }
        public int? created_at { get; set; }
        public string crv { get; set; }
        public int? expired_at { get; set; }
        public string kid { get; set; }
        public string kty { get; set; }
        public string use { get; set; }
        public string x { get; set; }
        public string y { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var signedJwt = "eyJhbGciOiJFUzI1NiIsImtpZCI6IjZjNTUxNmUxLTkyZGMtNDc5ZS1hOGZmLTVhNTE5OTJlMDAwMSIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1OTY3MzA4ODMsInJlcXVlc3RfYm9keV9zaGEyNTYiOiI4NDMyODhkMWMxYmM0NzhlMTBhOTM2NWQ1YjIzY2U5ZWZlY2E2ZjdkYjA3NDQ3Y2JmNjU4YTg3ZjEzZjI1ZjJmIn0.3yQY6gtNq0lQlx6eNLO_3coGqf2VkX2CBRWam9Lz0dcVvr8h4LkYfuZMwQf1fzZ_XXHEV_o17LciyBC-O72UUw";

            var jwkJson = "{\"alg\": \"ES256\",\"created_at\": 1560466143, \"crv\": \"P -256\", \"expired_at\": null, \"kid\": \"6c5516e1-92dc-479e-a8ff-5a51992e0001\", \"kty\": \"EC\", \"use\": \"sig\", \"x\": \"35lvC8uz2QrWpQJ3TUH8t9o9DURMp7ydU518RKDl20k\", \"y\": \"I8BuXB2bvxelzJAd7OKhd-ZwjCst05Fx47Mb_0ugros\"}";

            var jwk = JsonSerializer.Deserialize<JWK> (jwkJson);
            
            var publicECCKey = EccKey.New(WebEncoders.Base64UrlDecode(jwk.x), WebEncoders.Base64UrlDecode(jwk.y)) ;

            var claims = Jose.JWT.Decode(signedJwt, publicECCKey, JwsAlgorithm.ES256);
        }
    }
}

x и y кодируются Base64Url в jwk, поэтому вам нужно использовать декодер Base64Url, чтобы преобразовать его в byte[]. Я использовал для него Base64UrlDecode , но вы, конечно, можете использовать любое другое решение.

...