简体   繁体   English

c# Jose-Jwt:来自 KeyPair 字符串的签名和加密

[英]c# Jose-Jwt: Signed and Encrpyt from KeyPair string

I'm a newbie in jwt and after read a lot of web pages I've not found examples of how to generate a token ( signed and encrypted ) with keypairs generated from this website https://mkjwk.org/ .我是 jwt 的新手,在阅读了很多网页后,我没有找到如何使用从本网站https://mkjwk.org/生成的密钥对生成令牌(签名和加密)的示例。 I think it can't be very difficult.我认为这不会很困难。 I think this is the way to generate the signed token (I don't know if it's correct):我认为这是生成签名令牌的方式(不知道是否正确):

        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);

I get a token (I think is signed) but if I put this token in this web site https://jwt.io/ , I get an error "Invalid Signature".我得到一个令牌(我认为已签名),但是如果我将此令牌放在此网站https://jwt.io/ 中,则会收到错误“签名无效”。 Also I would like to encrypt this token with the public key.另外我想用公钥加密这个令牌。 So I do this:所以我这样做:

// 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);

But I always get the error "RsaKeyManagement alg expects key to be of RSACryptoServiceProvider type.".但我总是收到错误“RsaKeyManagement alg 期望密钥为 RSACryptoServiceProvider 类型。”。 I've already search about this error but I don't have anything clear.我已经搜索过这个错误,但我没有什么清楚的。 Please, anyone can help me?拜托,有人可以帮我吗? I'm not sure if I'm on the right way.我不确定我是否走对了路。

I use jose-jwt for .net because I've read that the library System.IdentityModel.Tokens.Jwt can't encrypt.我将 jose-jwt 用于 .net,因为我读过库 System.IdentityModel.Tokens.Jwt 无法加密。

Thank you.谢谢你。 Regards.问候。

In this case I had a jwk and I wanted to sign it with my private key and encrypt it with a customer public key with c# jose-jwt library .在这种情况下,我有一个 jwk,我想用我的私钥对其进行签名,并使用带有c# jose-jwt library的客户公钥对其进行加密。 This jwk is the same all the time, so I only need to generate it once.这个jwk一直都一样,所以我只需要生成一次。 To do that, you need to create an RSA object and then use the Encode method of the library to sign and encrypt.为此,您需要创建一个 RSA 对象,然后使用库的 Encode 方法进行签名和加密。 A jwk has severals parameters: jwk 有几个参数:

JSON Web Key (JWK): A JSON object that represents a cryptographic key. JSON Web Key (JWK):表示加密密钥的 JSON 对象。 The members of the object represent properties of the key, including its value.对象的成员代表键的属性,包括它的值。 These are some of the parameters:这些是一些参数:

p = 'RSA secret prime'; p = 'RSA 秘密素数'; kty = 'Key Type'; kty = '密钥类型'; q = 'RSA secret prime'; q = 'RSA 秘密素数'; d = 'RSA secret exponent'; d = 'RSA 秘密指数'; e = 'RSA public exponent'; e = 'RSA 公共指数'; kid = 'Key ID';孩子= '钥匙ID'; n = 'RSA public modulus'; n = 'RSA 公共模数'; use = 'Public Key Use'; use = '公钥使用'; alg = 'Algorithm' alg = '算法'

But in my case I only had some of them: d, e, n, kty, use, kid, alg.但就我而言,我只有其中的一些:d、e、n、kty、use、kid、alg。 The problem is that if you have e and d parameters, you also need p and q , because you can't construct private key with .NET without primes (P and Q).问题是如果你有 e 和 d 参数,你还需要p 和 q ,因为你不能在没有素数(P 和 Q)的情况下用 .NET 构造私钥

The solution was to part the problem in two parts:解决方案是将问题分为两部分:

JAVA part: create a complete jwk with the Nimbus JOSE+JWT JAVA library : JAVA 部分:使用Nimbus JOSE+JWT JAVA 库创建一个完整的 jwk:

C# parts: Use the previous jwk to create an RSA object in C# with c# jose-jwt library . C#部分:使用之前的jwk在C#中用c#jose-jwt库创建一个RSA对象。 Like this:像这样:

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);

Once you have an RSA object, you can sign it:拥有 RSA 对象后,您可以对其进行签名:

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

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

You can find the original solution in the library author web page .您可以在库作者网页中找到原始解决方案。

Regards.问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM