Saturday, November 24, 2018

Generating the Single Sign-on Authentication Token using C#


Generating the Single Sign-on Authentication Token using C#

Mapping a User using SuiteTalk sample using C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetSuiteAuthToken.NetSuiteServiceReference2011_2;
using System.Security.Cryptography;
using System.IO;
using Mono.Math;

namespace NetSuiteAuthToken
{
    class Program
    {
        static void Main(string[] args)
        {
            NetSuitePortType port = new NetSuitePortTypeClient();
            SsoCredentials ssoCreds = new SsoCredentials();

            String mappingString = "<NS USER MAPPING STRING>";
            String nsuseremail = "<NS USER EMAIL>";
            String password = "<NS PASSWORD>";
            String NSAccountID = "<NS ACCOUNT ID>";
            String partnerID = "<Partner ID>";
            String privateKeyPath = "<Private KEY Path>";

            ssoCreds.email = nsuseremail;
            ssoCreds.password = password;
            ssoCreds.account = NSAccountID;
            ssoCreds.partnerId = partnerID;

            RecordRef recordRef = new RecordRef();
            recordRef.internalId = "3";

            ssoCreds.role = recordRef;

            String authToken = createAuthToken(NSAccountID, mappingString, privateKeyPath);
            Console.WriteLine("Auth Token: " + authToken);
            ssoCreds.authenticationToken = authToken.Trim();

            mapSsoRequest ssoReq = new mapSsoRequest();

            ssoReq.ssoCredentials = ssoCreds;
            ssoReq.partnerInfo = new PartnerInfo();
            ssoReq.applicationInfo = new ApplicationInfo();

            mapSsoResponse ssoRes = null;

            ssoRes = port.mapSso(ssoReq);

            Console.WriteLine("Status: " + ssoRes.sessionResponse.status.isSuccess);
            Console.WriteLine("userId: " + ssoRes.sessionResponse.userId.name);

            Console.Read();
        }

        static String createAuthToken(String NSAccountID, String mappingString, String privateKeyPath)
        {
            String authToken = "";

            RSAParameters rsaParam = DecodeRSAPrivateKey(GetFileBytes(privateKeyPath));

            byte[] encryptedBytes;
            double millis = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
            String millisStr = (millis + "");
            millisStr = millisStr.Substring(0, millisStr.Length - (millisStr.Length - millisStr.IndexOf('.')));
            String plainText = NSAccountID + " " + mappingString + " " + millisStr;

            byte[] toEncrypt = StrToByteArray(plainText.Trim());
            encryptedBytes = privateEncrypt(toEncrypt, rsaParam);
            authToken = ByteToStr(encryptedBytes);
            return authToken;
        }

        public static byte[] privateEncrypt(byte[] toEncrypt, RSAParameters rsaParam)
        {
            BigInteger modulus = new BigInteger(rsaParam.Modulus);
            int modLength = getSignificantLength(rsaParam.Modulus);
            BigInteger D = new BigInteger(rsaParam.D);
            BigInteger data = new BigInteger(pkcs1PrivPad(toEncrypt, modLength));
            byte[] encrypted = zeroPad(data.ModPow(D, modulus).GetBytes(), modLength);
            return encrypted;
        }

        private static byte[] zeroPad(byte[] raw, int modLength)
        {
            byte[] returnMe = new byte[modLength];

            int srcStart = Math.Max(raw.Length - modLength, 0);
            int dstStart = Math.Max(0, modLength - raw.Length);
            int length = Math.Min(modLength, raw.Length);
            Array.Copy(raw, srcStart, returnMe, dstStart, length);
            for (int i = 0; i < modLength - raw.Length; i++) { returnMe[i] = 0; };
            return returnMe;
        }

        private static int getSignificantLength(byte[] raw)
        {
            int i = 0;
            while (raw[i] == 0) { i++; };
            return raw.Length - i;
        }

        private static byte[] pkcs1PrivPad(byte[] raw, int modLength)
        {
            MemoryStream os = new MemoryStream();
            int padLength = modLength - raw.Length;
            if (padLength < 11) return raw;
            os.WriteByte(0);
            os.WriteByte(1);
            for (int i = 2; i < padLength - 1; i++)
            {
                os.WriteByte(0xFF);
            }
            os.WriteByte(0);
            os.Write(raw, 0, raw.Length);
            return os.ToArray();
        }

        private static byte[] GetFileBytes(String filename)
        {
            if (!System.IO.File.Exists(filename))
                return null;
            Stream stream = new FileStream(filename, FileMode.Open);
            int datalen = (int)stream.Length;
            byte[] filebytes = new byte[datalen];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(filebytes, 0, datalen);
            stream.Close();
            return filebytes;
        }

        public static byte[] StrToByteArray(string str)
        {
            return System.Text.Encoding.UTF8.GetBytes(str);
        }

        public static String ByteToStr(byte[] bytes)
        {
            String hex = BitConverter.ToString(bytes);
            hex = hex.Replace("-", "");
            return hex;
        }

        public static RSAParameters DecodeRSAPrivateKey(byte[] privkey)
        {
            byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;

            MemoryStream mem = new MemoryStream(privkey);
            BinaryReader binr = new BinaryReader(mem);
            RSAParameters RSAparams = new RSAParameters();
            byte bt = 0;
            ushort twobytes = 0;
            int elems = 0;
            try
            {

                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130)
                {
                    binr.ReadByte();
                }
                else if (twobytes == 0x8230)
                {
                    binr.ReadInt16();
                }
                else
                {
                    return RSAparams;
                }
                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102)
                    return RSAparams;
                bt = binr.ReadByte();
                if (bt != 0x00)
                    return RSAparams;


                elems = GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                E = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                D = binr.ReadBytes(elems);

                RSAparams.Modulus = MODULUS;
                RSAparams.Exponent = E;
                RSAparams.D = D;
                return RSAparams;
            }
            catch (Exception)
            {
                return RSAparams;
            }
            finally { binr.Close(); }
        }

        private static int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            byte lowbyte = 0x00;
            byte highbyte = 0x00;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
            {
                count = binr.ReadByte();
            }
            else
                if (bt == 0x82)
                {
                    highbyte = binr.ReadByte();
                    lowbyte = binr.ReadByte();
                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                    count = BitConverter.ToInt32(modint, 0);
                }
                else
                {
                    count = bt; 
                }

            while (binr.ReadByte() == 0x00)
            { 
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current);
            return count;
        }

    }
}

Used C# BigInteger Class by Chew Keong TAN
http://www.codeproject.com/Articles/2728/C-BigInteger-Class

No comments:

Post a Comment