SUPERCAT.DEV

Benvenut* sul mio blog

CSHARP

JWT in C#

08-03-2024

Codifica e decodifica token JWT

Da GIT BASH

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

Da console di gestione pacchetti

Install-Package BouncyCastle.Cryptography
Install-Package jose-jwt

Verifica JWT dal sito https://jwt.io/

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

namespace consoleJWT
{
    class Program
    {
        static void Main(string[] args)
        {
            string publicKey = File.ReadAllText("public.key");
            string privateKey = File.ReadAllText("private.key");

            Console.WriteLine("publicKey:");
            Console.WriteLine(publicKey);
            Console.WriteLine("privateKey:");
            Console.WriteLine(privateKey);

            var claims = new List<Claim>();
            claims.Add(new Claim("utente", "Gatto"));
            claims.Add(new Claim("cliente", "123456"));

            try
            {
                var token = CreateToken(claims, privateKey);
                Console.WriteLine("token:");
                Console.WriteLine(token);
                Console.WriteLine(Environment.NewLine);

                // Creo un errore nel token così mi da => "Invalid signature"
                //token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dGVudGUiOiJST0xMQU5ESU5FIiwiY2xpZW50ZSI6IjEyMzQ1NiJ9.KIRYNtUnY3wLzSId0a3-oVu20csOw1Hsqqif_FFq59zeO-_l0a2C549cdBJq9E3Lpg-vVeFhDlnjEH1Jrs6qCA";

                var payload = DecodeToken(token, publicKey);
                Console.WriteLine("payload:");
                Console.WriteLine(payload);
                Console.WriteLine(Environment.NewLine);
            }
            catch (Jose.IntegrityException ex)
            {
                Console.WriteLine("Firma non valida");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Errore: {ex.Message}");
            }
                                
            Console.Write("Premi un tasto per continuare... ");
            Console.ReadKey();
        }

        public static string CreateToken(List<Claim> claims, string privateRsaKey)
        {
            RSAParameters rsaParams;
            using (var tr = new StringReader(privateRsaKey))
            {
                var pemReader = new PemReader(tr);
                var privateRsaParams = pemReader.ReadObject() as Org.BouncyCastle.Crypto.Parameters.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);
            }
        }
    }
}