Arsen Ablaev
Arsen Ablaev

Reputation: 501

How to create JWT using RS512 algorithm with private key in C#?

I need to create JWT using RS512 and private key which is string value. I tried the following way:

        var privateKey = @"-----BEGIN PRIVATE KEY----- {some string data} -----END PRIVATE KEY-----";

        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(privateKey));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha512);
        var header = new JwtHeader(credentials);

        var now = DateTime.UtcNow;
        var payload = new JwtPayload
        {
            { "iss", "1198bef0-a0d52731-706e-4936-be46-1ae4b2b2e9bd" },
            { "iat", now },
            { "exp", now.AddMinutes(30) }
        };

        var secToken = new JwtSecurityToken(header, payload);
        var handler = new JwtSecurityTokenHandler();

        var tokenString = handler.WriteToken(secToken);

But it gets me the next error:

        NotSupportedException: IDX10634: Unable to create the SignatureProvider.
Algorithm: 'RS512', SecurityKey: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey, KeyId: '', InternalId: '546ecdc1-0c87-40b4-905e-88d3bfc032c3'.'
is not supported. The list of supported algorithms is available here: https://aka.ms/IdentityModel/supported-algorithms

I heard that I should use RsaSecurityKey instead of SymmetricSecurityKey for RS512, but I couldn't find how to use one with private key.

Thanks!

Upvotes: 0

Views: 3374

Answers (2)

pooonyy
pooonyy

Reputation: 21

In case if someone is struggling with this issue, you can try to do like this (I am using BouncyCastle and jose-jwt libraries):

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Jose;

public class Token
{
    public 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 RsaPrivateCrtKeyParameters;
            if (keyPair == null)
            {
                throw new Exception("Could not read RSA private key");
            }
            var privateRsaParams = keyPair;
            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, JwsAlgorithm.RS512);
        }
    }


    public string GetJwtToken()
    {
        string privateKey = @"-----BEGIN PRIVATE KEY-----{YOUR SECURED DATA}-----END PRIVATE KEY-----";

        var claims = new List<Claim>();
        claims.Add(new Claim("sub", "[email protected]"));
        claims.Add(new Claim("iss", "user"));
        claims.Add(new Claim("exp", "1671231233"));
        claims.Add(new Claim("iat", "1516239022"));

        return CreateToken(claims, privateKey);
    }
}

Upvotes: 2

Alex
Alex

Reputation: 3991

Updated Loading RSA Key by using BouncyCastle library

public static RsaSecurityKey PrivateKeyFromPem(string keyPairPem)
        {
            PemReader pemReader = new PemReader(new StringReader(keyPairPem));
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
            RsaPrivateCrtKeyParameters privateKeyParameters = (RsaPrivateCrtKeyParameters)keyPair.Private;
            RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(privateKeyParameters);
            return new RsaSecurityKey(rsaParameters);
        }


   public static void Main()
    {
    var privateKey = @"-----BEGIN PRIVATE KEY----- {some string data} -----END 
                     PRIVATE KEY-----";

        DateTime now = DateTime.Now;
        var payload = new JwtPayload
    {
        { "iss", "1198bef0-a0d52731-706e-4936-be46-1ae4b2b2e9bd" },
        { "iat", now },
        { "exp", now.AddMinutes(30) }
    };

        var credentials =new SigningCredentials(
          PrivateKeyFromPem(privateKey),
          SecurityAlgorithms.RsaSha512
        );
        var header = new JwtHeader(signingCredentials: credentials);

        var jst = new JwtSecurityToken(header, payload);
        var tokenHandler = new JwtSecurityTokenHandler();
        string assertion = tokenHandler.WriteToken(jst);
        Console.WriteLine(assertion);
    }

you can go to https://jwt.io/ and check the result with your public an privet keys. extract from this article hope find it useful.

Upvotes: 0

Related Questions