• Skip to main content
  • Skip to primary sidebar
  • Skip to secondary sidebar
  • Skip to footer

Coding Still

  • Home
  • About

Create and sign JWT token with RS256 using the private key

February 24, 2018 By _tasos 16 Comments

In this article we will see how we can create and sign a JWT token with the RS256 algorithm. This function is complementary to the validate function I posted some time ago.

Here is the Sign(...) function that can create a RS256 signed JWT token. It makes use of the BouncyCastle library. It is available as a NuGet package with version 1.8.1.

using System;
using System.Collections.Generic;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
 
public string Sign(string payload, string privateKey)
{
    List segments = new List();
    var header = new { alg = "RS256", typ = "JWT" };
 
    DateTime issued = DateTime.Now;
    DateTime expire = DateTime.Now.AddHours(10);
 
    byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
    byte[] payloadBytes = Encoding.UTF8.GetBytes(payload);
 
    segments.Add(Base64UrlEncode(headerBytes));
    segments.Add(Base64UrlEncode(payloadBytes));
 
    string stringToSign = string.Join(".", segments.ToArray());
 
    byte[] bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
 
    byte[] keyBytes = Convert.FromBase64String(privateKey);
 
    var privKeyObj = Asn1Object.FromByteArray(keyBytes);
    var privStruct = RsaPrivateKeyStructure.GetInstance((Asn1Sequence)privKeyObj);
 
    ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");
 
    sig.Init(true, new RsaKeyParameters(true, privStruct.Modulus, privStruct.PrivateExponent));
 
    sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
    byte[] signature = sig.GenerateSignature();
 
    segments.Add(Base64UrlEncode(signature));
    return string.Join(".", segments.ToArray());
}

Here are some helper functions used in the above snippet.

// from JWT spec
private static string Base64UrlEncode(byte[] input)
{
    var output = Convert.ToBase64String(input);
    output = output.Split('=')[0]; // Remove any trailing '='s
    output = output.Replace('+', '-'); // 62nd char of encoding
    output = output.Replace('/', '_'); // 63rd char of encoding
    return output;
}
 
private static byte[] Base64UrlDecode(string input)
{
    var output = input;
    output = output.Replace('-', '+'); // 62nd char of encoding
    output = output.Replace('_', '/'); // 63rd char of encoding
    switch (output.Length % 4) // Pad with trailing '='s
    {
        case 0: break; // No pad chars in this case
        case 1: output += "==="; break; // Three pad chars
        case 2: output += "=="; break; // Two pad chars
        case 3: output += "="; break; // One pad char
        default: throw new System.Exception("Illegal base64url string!");
    }
    var converted = Convert.FromBase64String(output); // Standard base64 decoder
    return converted;
}

The helper functions are the same ones found in the validate function.

This function is based on the code snippet found in this SO question.

Update 1: You can check this post here, where I have created a C# library that manages Jwt tokens.

Update 2: If you are having trouble making your keys work, have a look in my Check your RSA private and public keys post and make sure to check the Additional Resources section as well

Filed Under: .NET Development Tagged With: Bouncy Castle, JWT

Reader Interactions

Comments

  1. Murali says

    June 11, 2018 at 18:21

    Where is the Base64Encoding() definition?

    Reply
    • _tasos says

      June 14, 2018 at 19:34

      Hi Murali, you can find the helper functions in this post.

      Reply
  2. Fabio says

    July 6, 2018 at 18:57

    Hi, can you give a simple example of how you generate the private key?

    Reply
    • _tasos says

      July 14, 2018 at 12:28

      Hi Fabio, I used openssl to generate the private and public keys

      Private key:

      openssl genrsa -out private.key 2048

      Public key:

      openssl rsa -in private.key -outform PEM -pubout -out public.pem

      Check also this post: OpenSSL Command Cheatsheet

      Reply
  3. Raju Chapagain says

    December 11, 2018 at 09:46

    Base64UrlEncode function is not there? Could you please explain whether it is built in function and I am missing to include any reference or it is custom function and You have missed to put in your code.

    Reply
    • _tasos says

      December 11, 2018 at 19:06

      Hi Raju, thanks for noticing! I updated the code accordingly.

      Reply
  4. Rushal Maksane says

    December 24, 2018 at 14:07

    How can i verify using public key? with RSA384 algorithm? Any help is appreciated.

    Reply
    • _tasos says

      December 24, 2018 at 16:36

      Hi Rushal,

      You can use the code here with RS384. Just replace 256 to 384 and it should work. Also check here to see how you can verify using the public key.

      Reply
  5. Romeo Arnoza says

    February 7, 2019 at 15:23

    Hi Tasos,

    I’m encountering below error on this line:

    var privStruct = RsaPrivateKeyStructure.GetInstance((Asn1Sequence)privKeyObj);

    System.InvalidCastException: ‘Unable to cast object of type ‘Org.BouncyCastle.Asn1.DerSequence’ to type ‘Org.BouncyCastle.Asn1.DerInteger’.’

    Reply
  6. Eduardo Nardi says

    March 25, 2019 at 21:46

    Hi Romeo,

    Though an older question, I’d gotten the same error, I don’t know why, I think that some deprecated code.

    I changed this:

    var privKeyObj = Asn1Object.FromByteArray(keyBytes);
    var privStruct = RsaPrivateKeyStructure.GetInstance((Asn1Sequence)privKeyObj);
    sig.Init(true, new RsaKeyParameters(true, privStruct.Modulus, privStruct.PrivateExponent));

    For this:

    var asymmetricKeyParameter = PrivateKeyFactory.CreateKey(keyBytes);
    var rsaKeyParameter = (RsaKeyParameters)asymmetricKeyParameter;
    sig.Init(true, rsaKeyParameter);

    And it worked fine for me.

    Reply
    • _tasos says

      March 26, 2019 at 08:02

      Hi Eduardo,

      Thanks for your reply.

      I tried your change and I am getting the following error when calling

      PrivateKeyFactory.CreateKey(keyBytes)

      Unknown object in GetInstance: Org.BouncyCastle.Asn1.DerInteger
      Parameter name: obj’

      Which version of BouncyCastle are you using? I checked my code with 1.8.2 and 1.8.5 and it is working without issues.

      Reply
  7. Eduardo Nardi says

    March 27, 2019 at 14:39

    Hi _tasos,

    Before all, congratulation for your post, it help me a lot !!!

    I’m using 1.8.4 and getting error invalid cast, I’ll try 1.8.5 version.

    Reply
    • _tasos says

      March 28, 2019 at 22:02

      Thank you, I am glad you found it useful!

      Now, regarding the issue, I am guessing that the private key might be different, thus the need to load it with a different way. I am wondering if you have the openssl command that generates you private key so that I can test against my code.

      Reply
  8. _amy says

    September 16, 2019 at 13:18

    byte[] keyBytes = Convert.FromBase64String(privateKey);
    I’m encountering error on this line. My private key is in pem format but it says unable to convert using base 64. How did you guys resolve this?

    Reply
  9. Raheel says

    June 10, 2020 at 12:55

    Hi _tasos,

    How to define payload with multiple values like:

    payload = {
    “iss”: issuer,
    “sub”: client_id,
    “aud”: aud
    }

    Reply
    • _tasos says

      June 14, 2020 at 13:08

      Hi Raheel,

      The payload can be anything. If you need it to be a JSON object, you’ll need to serialize it. Have a look here for examples.

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Categories

  • .NET Development
  • ASP.NET
  • Databases
  • Fun
  • IIS
  • JavaScript
  • Web Development

Tags

.NET Core Android ANTLR ASP.NET Ajax ASP.NET Core ASP.NET MVC ASP.NET Web Forms AWS Bouncy Castle Chartjs cli Client info detection Comic Continuous integration CSS Data backup Date handling Firebase Firefox addons Github HigLabo HTML5 Image manipulation jQuery JWT MySQL Nodejs Nuget OAuth Objectionjs OOP openssl Oracle ORM PHP Regular expressions SEO Social media SQL SQL Server UI/UX Url rewriting Videos Visual Studio Web design

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Secondary Sidebar

Archives

  • July 2020
  • March 2020
  • August 2019
  • December 2018
  • November 2018
  • February 2018
  • August 2016
  • June 2016
  • May 2016
  • February 2016
  • January 2016
  • August 2015
  • July 2015
  • October 2014
  • July 2014
  • November 2013
  • April 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • May 2012
  • February 2012
  • December 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010

Footer

Recent Posts

  • Anatomy of an Objection.js model
  • Check your RSA private and public keys
  • Round functions on the Nth digit
  • Send FCM Notifications in C#
  • Jwt Manager
  • Things around the web #5
  • Query JSON data as relational in MySQL
  • Create and sign JWT token with RS256 using the private key
  • Drop all database objects in Oracle
  • Create and deploy a Nuget package

Latest tweets

  • Geekiness Intensifies.. NASA used Three.js to render a real-time simulation of this week's NASA rover landing on M… https://t.co/orgkXnYj9O February 19, 2021 18:12
  • Things I Wished More Developers Knew About Databases https://t.co/h4gfq6NJgo #softwaredevelopment #databases May 3, 2020 12:52
  • How a Few Lines of Code Broke Lots of Packages https://t.co/p7ZSiLY5ca #javascript May 3, 2020 12:48
  • Can someone steal my IP address and use it as their own? https://t.co/HoQ7Z3BG69 January 24, 2020 13:27
  • Organizational complexity is the best predictor of bugs in a software module https://t.co/aUYn9hD4oa #softwaredevelopment January 13, 2020 08:24
  • http://twitter.com/codingstill

Misc Links

  • George Liatsos Blog
  • Plethora Themes
  • C# / VB Converter
  • Higlabo: .NET library for mail, DropBox, Twitter & more

Connect with me

  • GitHub
  • LinkedIn
  • RSS
  • Twitter
  • Stack Overflow

Copyright © 2021 · eleven40 Pro on Genesis Framework · WordPress · Log in