Sample Code in C#.net

Authentication sample code for Version 1.04

using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace EinvoiceAuth
{
    class Program
    {
        static void Main(string[] args)
        {
            call_server_api();
        }
        public static void call_server_api()
        {
            try
            {
                string public_key = "<Public Key>";
                HttpClient client = new HttpClient();
                string uri = "<URL>/v1.04/auth";
                client.DefaultRequestHeaders.Add("client-id", "<Client ID>");
                client.DefaultRequestHeaders.Add("client-secret", "<Client Secret>");
                string userName = "<User Id>";
                string password = "<Password>";
                client.DefaultRequestHeaders.Add("gstin", "<GSTIN>");
                byte[] _aeskey = generateSecureKey();
                string straesKey = Convert.ToBase64String(_aeskey);
                RequestPayloadN aRequestPayload = new RequestPayloadN();
                Auth data = new Auth();
                data.Password = password;
                data.AppKey = straesKey;
                data.UserName = userName;
                data.ForceRefreshAccessToken = false;
                string authStr = JsonConvert.SerializeObject(data);
                byte[] authBytes = System.Text.Encoding.UTF8.GetBytes(authStr);
                aRequestPayload.Data = Encrypt(Convert.ToBase64String(authBytes), public_key);
                string abc = JsonConvert.SerializeObject(aRequestPayload);
                HttpResponseMessage res = client.PostAsJsonAsync(uri, aRequestPayload).Result;
                if (res.IsSuccessStatusCode)
                {
                    Console.WriteLine("Call is success");
                    string verification = res.Content.ReadAsStringAsync().Result;
                    Console.WriteLine($"Response{verification}");
                    AuthResponse authResponse = res.Content.ReadAsAsync<AuthResponse>().Result;
                    string sek = DecryptBySymmerticKey(authResponse.Data.Sek, _aeskey);
                    Console.WriteLine($"Sek {sek}");
                }
                else
                {
                    var stream = res.Content.ReadAsStreamAsync().Result;
                    StreamReader reader = new StreamReader(stream);
                    string text = reader.ReadToEnd();
                    string err = res.ReasonPhrase;
                    Console.WriteLine($"error Response{text} reason{err}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        public static string DecryptBySymmerticKey(string encryptedText, byte[] key)
        {
            try
            {
                byte[] dataToDecrypt = Convert.FromBase64String(encryptedText);
                var keyBytes = key;
                AesManaged tdes = new AesManaged();
                tdes.KeySize = 256;
                tdes.BlockSize = 128;
                tdes.Key = keyBytes;
                tdes.Mode = CipherMode.ECB;
                tdes.Padding = PaddingMode.PKCS7;
                ICryptoTransform decrypt__1 = tdes.CreateDecryptor();
                byte[] deCipher = decrypt__1.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
                tdes.Clear();
                string EK_result = Convert.ToBase64String(deCipher);
                // var EK = Convert.FromBase64String(EK_result);
                // return EK;
                return EK_result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static byte[] generateSecureKey()
        {
            Aes KEYGEN = Aes.Create();
            byte[] secretKey = KEYGEN.Key;
            return secretKey;
        }
        public static string Encrypt(string data, string key)
        {
            byte[] keyBytes =
           Convert.FromBase64String(key); // your key here
            AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
            RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
            RSAParameters rsaParameters = new RSAParameters();
            rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
            rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(rsaParameters);
            byte[] plaintext = Encoding.UTF8.GetBytes(data);
            byte[] ciphertext = rsa.Encrypt(plaintext, false);
            string cipherresult = Convert.ToBase64String(ciphertext);
            //string cipherresult = Encoding.ASCII.GetString(ciphertext);
            return cipherresult;
        }
       
    }
    public class Auth
    {
        public string Password { get; set; }
        public string AppKey { get; set; }
        public string UserName { get; set; }
        public Boolean ForceRefreshAccessToken { get; set; }
    }
    public class RequestPayloadN
    {
        public string Data { get; set; }
    }
    public class AuthResponse
    {
        public string Status { get; set; }
        public List<ErrorDetail> ErrorDetails { get; set; }
        public List<InfoDtl> InfoDtls { get; set; }
        public class ErrorDetail
        {
            public string ErrorCode { get; set; }
            public string ErrorMessage { get; set; }
        }
        public class InfoDtl
        {
            public string InfCd { get; set; }
            public List<Infodata> Desc { get; set; }
        }
        public class Infodata
        {
            public string ErrorCode { get; set; }
            public string ErrorMessage { get; set; }
        }
        public data Data { get; set; }
        public class data
        {
            public string ClientId { get; set; }
            public string UserName { get; set; }
            public string AuthToken { get; set; }
            public string Sek { get; set; }
            public string TokenExpiry { get; set; }
            public static implicit operator data(string v)
            {
                throw new NotImplementedException();
            }
        }
    }
}        

Symmetric Decryption (AES)

The following C#.Net code snippet can be used for decrypting the encrypted sek using the appkey.

Here the encryptedSek is the one that is received in response to the authentication.

      public static byte[] DecryptBySymmetricKey(string encryptedSek, byte[] appkey)
          {
            //Decrypting SEK
            try
              {
                byte[] dataToDecrypt = Convert.FromBase64String(encryptedSek);
                var keyBytes = appkey;
                AesManaged tdes = new AesManaged();
                tdes.KeySize = 256;
                tdes.BlockSize = 128;
                tdes.Key = keyBytes;
                tdes.Mode = CipherMode.ECB;
                tdes.Padding = PaddingMode.PKCS7;
                ICryptoTransform decrypt__1 = tdes.CreateDecryptor();
                byte[] deCipher = decrypt__1.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
                tdes.Clear();
                string EK_result = Convert.ToBase64String(deCipher);
                return EK_result;
             }
                catch (Exception ex)
                    {
                        throw ex;
                    }
          }
    

Symmetric Key Encryption (AES)

The following C#.Net code snippet can be used for encrypting the data using the symmetric key.

The decrypted sek need to be passed here.(It is got by decrypting the obtained SEK after successful authentication)

          public static string EncryptBySymmetricKey(string jsondata, string sek)
              {
              //Encrypting SEK
              try
                 {
                    byte[] dataToEncrypt = Convert.FromBase64String(jsondata);
                    var keyBytes = Convert.FromBase64String(sek);
                    AesManaged tdes = new AesManaged();
                    tdes.KeySize = 256;
                    tdes.BlockSize = 128;
                    tdes.Key = keyBytes;
                    tdes.Mode = CipherMode.ECB;
                    tdes.Padding = PaddingMode.PKCS7;
                    pICryptoTransform encrypt__1 = tdes.CreateEncryptor();
                    byte[] deCipher = encrypt__1.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
                    tdes.Clear();
                    string EK_result = Convert.ToBase64String(deCipher);
                    return EK_result;
                }
                    catch (Exception ex)
                       {
                         throw ex;
                       }
             }
          

Decoding the Signed eInvoice

  public static string Decode(string token)
    {
       var parts = token.Split('.');
       var header = parts[0];
       var payload = parts[1];
       var signature = parts[2];
       byte[] crypto = Base64UrlDecode(parts[2]);
       var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
       var headerData = JObject.Parse(headerJson);
       var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
       var payloadData = JObject.Parse(payloadJson);        
       return headerData.ToString() + payloadData.ToString();
     }

Verifying the Signed eInvoice

Please note the ‘ProdPubKey.cer’ mentioned here is the Key provided for the verification of the signed content.

 private  static bool ValidateToken(string token)
    {
      var handler = new JsonWebTokenHandler();
      string path = HttpContext.Current.Server.MapPath("~") + "\\EncDesc\\ProdPubKey.cer";
      X509Certificate2 signingPublicCert = new X509Certificate2(path);
      Microsoft.IdentityModel.Tokens.X509SecurityKey publickey = new Microsoft.IdentityModel.Tokens.X509SecurityKey(signingPublicCert);
      TokenValidationResult result = handler.ValidateToken(token,
      new TokenValidationParameters
         {
          ValidIssuer = "NIC",
          ValidateAudience = false,
          IssuerSigningKey = publickey,
          ValidateLifetime = false
         });
        bool isValid = result.IsValid;
        SecurityToken securityToken = handler.ReadToken(token);
        return isValid;
    }