How to create an encrypted JWT in C # using RS256 with RSA private key

I am using the jose-jwt library and want to create a signed JWT in C # using the RS256 algorithm for encryption. I have no experience in cryptography, so I apologize for my ignorance. I see the following example in the docs:

var payload = new Dictionary<string, object>()
{
    { "sub", "mr.x@contoso.com" },
    { "exp", 1300819380 }
};

var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;

string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);

which shows the use of the file p12, but how do I use the RSA key file in the form below? I am viewing documents for the X509Certificate2 but cannot see the options for RSA private keys. It seems to accept only PKCS7that I understand as public keys.

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp
wmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5
1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh
3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2
pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX
GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il
AkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF
L0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k
X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
-----END RSA PRIVATE KEY-----

Finally, what is the difference between the two options listed in the documents , and how to choose between them?

-------------------------- 1 ---------------------- ----

RS- * PS- *

CLR:

RS256, RS384, RS512 PS256, PS384, PS512 RSACryptoServiceProvider ( ) . CSP Microsoft Enhanced RSA AES Cryptographic Provider. RSAParameters. . Http://clrsecurity.codeplex.com/discussions/243156 .

-------------------------- 2 ---------------------- ----

CORECLR: RS256, RS384, RS512 RSA ( ) .

+9
6

, , , , .

RSA OpenSSL:

openssl genrsa -out privateKey.pem 512
openssl rsa -in privateKey.pem -pubout -out publicKey.pem

2 nuget:

  1. https://github.com/dvsekhvalnov/jose-jwt
  2. http://www.bouncycastle.org/csharp/

public static void Test()
{
        string publicKey = File.ReadAllText(@"W:\Dev\Temp\rsa_keys\publicKey.pem");
        string privateKey = File.ReadAllText(@"W:\Dev\Temp\rsa_keys\privateKey.pem");

        var claims = new List<Claim>();
        claims.Add(new Claim("claim1", "value1"));
        claims.Add(new Claim("claim2", "value2"));
        claims.Add(new Claim("claim3", "value3"));

        var token = CreateToken(claims, privateKey);
        var payload = DecodeToken(token, publicKey);
    }

    public static string CreateToken(List<Claim> claims, string privateRsaKey)
    {
        RSAParameters rsaParams;
        using (var tr = new StringReader(privateRsaKey))
        {
            var pemReader = new PemReader(tr);
            var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
            if (keyPair == null)
            {
                throw new Exception("Could not read RSA private key");
            } 
            var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters;
            rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams);
        }
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(rsaParams);
            Dictionary<string, object> payload = claims.ToDictionary(k => k.Type, v => (object)v.Value);
            return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
        }
    }

    public static string DecodeToken(string token, string publicRsaKey)
    {
        RSAParameters rsaParams;

        using (var tr = new StringReader(publicRsaKey))
        {
            var pemReader = new PemReader(tr);
            var publicKeyParams = pemReader.ReadObject() as RsaKeyParameters;
            if (publicKeyParams == null)
            {
                throw new Exception("Could not read RSA public key");
            }
            rsaParams = DotNetUtilities.ToRSAParameters(publicKeyParams);
        }
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(rsaParams);
            // This will throw if the signature is invalid
            return Jose.JWT.Decode(token, rsa, Jose.JwsAlgorithm.RS256);  
        }
    }

https://jwt.io/

+17

, ,

private X509Certificate2 GetByThumbprint(string Thumbprint)
{
    var localStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    localStore.Open(OpenFlags.ReadOnly);
    return localStore.Certificates//.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, false)
        .Find(X509FindType.FindByThumbprint, Thumbprint, false)
        .OfType<X509Certificate2>().First();
}

:

private JwtSecurityToken GenerateJWT()
{
    var securityKey = new Microsoft.IdentityModel.Tokens.X509SecurityKey(GetByThumbprint("YOUR-CERT-THUMBPRINT-HERE"));

    var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "RS256");

    var JWTHeader = new JwtHeader(credentials);

    var payload = new JwtPayload
    {
        { "iss", "Issuer-here"},
        { "exp", (Int32)(DateTime.UtcNow.AddHours(1).Subtract(new DateTime(1970, 1, 1))).TotalSeconds},
        { "iat", (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds}
    };

    var token = new JwtSecurityToken(JWTHeader, payload);
    return token;
}
+1

.NET 4.6, :

string token = "eyJhbGciOiJSUzI1NiIsInR....";
string certificate = "MIICnzCCAYcCBgFd2yEPx....";
var publicKey = new X509Certificate2(Convert.FromBase64String(certificate )).GetRSAPublicKey();
string decoded = JWT.Decode(token, publicKey, JwsAlgorithm.RS256);
0
  • RS256 - , .
  • JWT:

    var cert = new X509Certificate2(".\\key.cer");
    var rsa = (RSACryptoServiceProvider) cert.PublicKey.Key;
    
    var payload = new Dictionary<string, object>()
    {
      {"sub", "mr.x@contoso.com"},
      {"exp", 1300819380}
    };
    
    var encryptedToken =
      JWT.Encode(
        payload,
        rsa,
        JweAlgorithm.RSA_OAEP,
        JweEncryption.A256CBC_HS512,
        null);
    
0

JWT Bouncy Castle .

  1. JWT JWT
  2. Bouncy Castle , RS256

First, you need to convert the private key to the RSA parameter form. Then you need to pass the RSA parameters to the RSA algorithm as a private key. Finally, you use the JWT library to encode and sign the token.

    public string GenerateJWTToken(string rsaPrivateKey)
    {
        var rsaParams = GetRsaParameters(rsaPrivateKey);
        var encoder = GetRS256JWTEncoder(rsaParams);

        // create the payload according to your need
        var payload = new Dictionary<string, object>
        {
            { "iss", ""},
            { "sub", "" },
            // and other key-values 
        };

        // add headers. 'alg' and 'typ' key-values are added automatically.
        var header = new Dictionary<string, object>
        {
            { "{header_key}", "{your_private_key_id}" },
        };

        var token = encoder.Encode(header,payload, new byte[0]);

        return token;
    }

    private static IJwtEncoder GetRS256JWTEncoder(RSAParameters rsaParams)
    {
        var csp = new RSACryptoServiceProvider();
        csp.ImportParameters(rsaParams);

        var algorithm = new RS256Algorithm(csp, csp);
        var serializer = new JsonNetSerializer();
        var urlEncoder = new JwtBase64UrlEncoder();
        var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

        return encoder;
    }

    private static RSAParameters GetRsaParameters(string rsaPrivateKey)
    {
        var byteArray = Encoding.ASCII.GetBytes(rsaPrivateKey);
        using (var ms = new MemoryStream(byteArray))
        {
            using (var sr = new StreamReader(ms))
            {
                // use Bouncy Castle to convert the private key to RSA parameters
                var pemReader = new PemReader(sr);
                var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
                return DotNetUtilities.ToRSAParameters(keyPair.Private as RsaPrivateCrtKeyParameters);
            }
        }
    }

ps: the RSA private key must be in the following format:

----- BEGIN RSA PRIVATE KEY -----

{base64 formatted value}

----- END RSA PRIVATE KEY -----

0
source

Source: https://habr.com/ru/post/1650335/


All Articles