How to sign a JWT using RS256 with RSA private key

I know this post is old, but it took me forever to figure this out, so I thought I would share.

To test I created RSA keys using OpenSSL:

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

You will need the following 2 nuget packages:

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

Test Code

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

Create Token

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

Decode Token

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

I found https://jwt.io/ a great resource to test your tokens

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)