C# Jose-Jwt: подписано и зашифровано из строки KeyPair

Я новичок в jwt, и после прочтения многих веб-страниц я не нашел примеров того, как сгенерировать токен (подписанный и зашифрованный) с парами ключей, созданными на этом сайте https://mkjwk.org/. Я думаю, что это не может быть очень сложно. Я думаю, что это способ генерирования подписанного токена (я не знаю, является ли он правильным):

        RSACryptoServiceProvider rsaCrypto = new RSACryptoServiceProvider();

        var payload = new Dictionary<string, object>()
        {
            {"jti", "ORIGEN_" + Guid.NewGuid().ToString()},
            {"iat", DateTime.UtcNow},
            {"exp", DateTime.UtcNow.AddYears(1)},
            {"login", "USER" },
            {"password", "PASSWORD" },
            {"origen", "ORIGEN" }
        };

        // Contains both public and private keys to sign
        var headers = new Dictionary<string, object>()
        {
            { "kty", "RSA" },
            { "d", "A7Q8cttv_CSG4CJkX_xlU5lUoeRrCPZpyZx9eVaD7zi-tE7wDPKNmJPRP6uR_LA2YVXMmfY9w8q1_v_MiYxkYnFgZqNZlKdwucSQUlnfX5Tt806qh_323h5NnHrKweL-98_d8R4RuZXCWEQ3X0QDCVfccaLVVqLJy8S5zlx0aAVuBJxLxBHFRO700qdUN-RaMjHULoOnE1KbwmfKPfGlLL0YWPHQ9t-qIBh6OSZsDZh30K4VLF8sRXkGgn81_Byp4hK9tCfG98R6fWUM2_FCQrC9R1hO-KTsLffRzMboWe-2ymZGQfZKO-gtFaQH7_AjdVnQYMyKhSSCGYAAroSZAQ"},
            { "e", "AQAB" },
            { "use", "enc"},
            { "kid", "RPA" },
            { "alg", "RS256" },
            { "n", "qJPwMcHtb7xFGGczn20IiEtrPVehquyT6lxIJa_e4vcZE33uM6myVZWocTZWzTDmrNT3bJghEpLOhrgYatT3QnJIiTM9KAD01kYPc5cP5yo6Wmu0YjivqL3Rj7dUvi2pvl7juwYxt1_8zfdnBN5GpBIYcaY3ulVo_OSL7TOxJrua5IMhilQz6kqta3-Rgz3GSglOs94RHRvorYxMyHPQ6KhwSlh_zLzJQZ-0-AZ4yaMPdVwEaaEJpL-odYmRudX4E0t42dExLf_q1rpRfvTcdFSwfsJ7FmQcOtlc340WUgr4BHJfwrNIE4i-TFqrB4zSQJVKHlBfLeGKiYZQPD7igw" }
        };

        string tokenSigned = JWT.Encode(payload, rsaCrypto, JwsAlgorithm.RS256, headers);

Я получаю токен (я думаю, что он подписан), но если я помещаю этот токен на этот веб-сайт https://jwt.io/, я получаю сообщение об ошибке "Invalid Signature". Также я хотел бы зашифровать этот токен открытым ключом. Итак, я делаю это:

// Another public key to encrypt
headers = new Dictionary<string, object>()
        {
            { "kty", "RSA" },
            { "e", "AQAB" },
            { "use", "enc"},                
            { "alg", "RS256" },
            { "n", "ldMvqNDlz8-ABqEhqjtT0qvjKKbJMQ4J6GEi-7QrY-EUtyjCE7cOriHrYmbjt3o3zXwUTyOp0-twnF5j1HXFwVk7_XNsZz7LUmGNtmnqgB2iw2xhS7LAicN0RRgIbxWRDLOaaZ-49QumX6_r_jLNtIspKiFiuUNf2s0ipeAjWBFquiiqTMBd98z3pS-vC5y0CfzPbTSLSinikrHkIW2uO4FNHWZpoo8npn7vwWtAJjknWhaFi2s9P5kzUk4Mpbdx4DxUJ9ZvUi9SmdvH2vUzwGe0lxyvlw0DAMMWAT9TmsiKzBeXTY6rQ1-2Edn4F9S5kkPNOh1NqJoebz50-Bpl6w" }
        };

string tokenEncrypted = JWT.Encode(payload, tokenSigned , JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM, extraHeaders: headers);

Но я всегда получаю ошибку "RsaKeyManagement alg ожидает, что ключ будет иметь тип RSACryptoServiceProvider". Я уже искал об этой ошибке, но у меня нет ничего ясного. Пожалуйста, кто-нибудь может мне помочь? Я не уверен, что я на правильном пути.

Я использую jose-jwt для.net, потому что я прочитал, что библиотека System.IdentityModel.Tokens.Jwt не может зашифровать.

Спасибо. С уважением.

1 ответ

В этом случае у меня был jwk, и я хотел подписать его своим закрытым ключом и зашифровать его открытым ключом клиента с помощью библиотеки C# jose-jwt. Этот jwk все время один и тот же, поэтому мне нужно сгенерировать его только один раз. Для этого вам нужно создать объект RSA, а затем использовать метод Encode библиотеки для подписи и шифрования. JWK имеет несколько параметров:

JSON Web Key (JWK): объект JSON, представляющий криптографический ключ. Элементы объекта представляют свойства ключа, включая его значение. Вот некоторые из параметров:

p = "Секретное простое число RSA"; kty = 'Тип ключа'; q = "Секретное простое число RSA"; d = "Секретный показатель RSA"; e = 'открытый представитель RSA'; kid = 'Key ID'; n = 'Публичный модуль RSA'; use = 'Использование открытого ключа'; alg = 'Алгоритм'

Но в моем случае у меня были только некоторые из них: d, e, n, kty, use, kid, alg. Проблема в том, что если у вас есть параметры e и d, вам также нужны p и q, потому что вы не можете создать закрытый ключ с.NET без простых чисел (P и Q).

Решение было разделить проблему на две части:

Часть JAVA: создайте полный JWK с библиотекой JAVA Nimbus JOSE+JWT:

Части C#: используйте предыдущий jwk для создания объекта RSA в C# с библиотекой C# jose-jwt. Как это:

var js = new JavaScriptSerializer();    
// json is the result returned by java
var jwk = js.Deserialize<IDictionary<string, string>>(json);

byte[] p = Base64Url.Decode(jwk["p"]);
byte[] q = Base64Url.Decode(jwk["q"]);
byte[] d = Base64Url.Decode(jwk["d"]);
byte[] e = Base64Url.Decode(jwk["e"]);
byte[] qi = Base64Url.Decode(jwk["qi"]);
byte[] dq = Base64Url.Decode(jwk["dq"]);
byte[] dp = Base64Url.Decode(jwk["dp"]);
byte[] n = Base64Url.Decode(jwk["n"]);

RSA key = RSA.Create();
RSAParameters keyParams = new RSAParameters();
keyParams.P = p;
keyParams.Q = q;
keyParams.D = d;
keyParams.Exponent = e;
keyParams.InverseQ = qi;
keyParams.DP = dp;
keyParams.DQ = dq;
keyParams.Modulus = n;

key.ImportParameters(keyParams);

Если у вас есть объект RSA, вы можете подписать его:

var payload = new Dictionary<string, object>()
{       
    {"user", USER },
    {"password", PASSWORD }            
};

string tokenSigned = JWT.Encode(payload, key, JwsAlgorithm.RS256);

Вы можете найти оригинальное решение на веб-странице автора библиотеки.

С уважением.

Другие вопросы по тегам