Tuesday, December 11, 2018

Generating the Single Sign-on Authentication Token using VB.NET

Generating the Single Sign-on Authentication Token using VB.NET

Mapping a User using SuiteTalk  [VB.NET]

Option Explicit On
Imports System.Numerics
Imports System.IO
Imports System.Security.Cryptography
Imports NSAuthenticationToken.com.netsuite.webservices

Module Module1

    Dim TxtPath As String = "C:\"
    Dim privateKey As String = "<Private KEY Path>"

    Sub Main()

        Dim port As New NetSuiteService()

        Dim ssoCreds As New SsoCredentials()

        Dim nsuseremail As String = "<NS USER MAPPING STRING>"
        Dim password As String = "<NS PASSWORD>"
        Dim companyID As String = "<NS ACCOUNT ID>"
        Dim partnerID = "<PARTNER ID>"

        Dim authToken As String = createAuthToken(companyID, nsuseremail)

        Console.WriteLine("Auth Token: " & authToken)

        ssoCreds.email = nsuseremail
        ssoCreds.password = password
        ssoCreds.account = companyID
        ssoCreds.partnerId = partnerID

        Dim recordRef As New RecordRef()
        recordRef.internalId = "3"

        ssoCreds.role = recordRef

        ssoCreds.authenticationToken = authToken

        port.partnerInfo = New PartnerInfo()

        port.applicationInfo = New ApplicationInfo()

        Dim sessionResponse As SessionResponse = port.mapSso(ssoCreds)

        Console.WriteLine("Status: " & sessionResponse.status.isSuccess)
        Console.WriteLine("userId: " & sessionResponse.userId.name)

        Console.Read()

    End Sub

    Function createAuthToken(companyID As String, mappingString As String) As String
        Dim authToken As String = ""

        Dim rsaParam As RSAParameters = DecodeRSAPrivateKey(getFileBytes(privateKey))

        Dim millis As Double = (DateTime.UtcNow - New DateTime(1970, 1, 1)).TotalMilliseconds
        Dim millisStr As String = millis & ""
        millisStr = millisStr.Substring(0, millisStr.Length - (millisStr.Length - millisStr.IndexOf(".")))
        Dim plainText = companyID & " " & mappingString & " " & millisStr
        System.IO.File.WriteAllText(TxtPath & "Unencrypted.txt", plainText)
        Dim toEncrypt() As Byte = StringToByteArray(plainText.Trim())

        Dim encryptedBytes() As Byte = privateEncrypt(toEncrypt, rsaParam)
        authToken = ByteToString(encryptedBytes)

        createAuthToken = authToken
    End Function

    Function getFileBytes(filename As String) As Byte()
        If Not System.IO.File.Exists(filename) Then
            Return Nothing
        End If
        Dim stream As Stream = New FileStream(filename, FileMode.Open)
        Dim datalen As Integer = stream.Length
        Dim returnByte(0 To datalen - 1) As Byte
        stream.Seek(0, SeekOrigin.Begin)
        stream.Read(returnByte, 0, datalen)
        stream.Close()
        getFileBytes = returnByte
    End Function

    Function StringToByteArray(str As String) As Byte()
        StringToByteArray = System.Text.Encoding.UTF8.GetBytes(str)
    End Function

    Function ByteToString(bytes() As Byte) As String
        Dim hex As String = BitConverter.ToString(bytes)
        hex = hex.Replace("-", "")
        ByteToString = hex
    End Function

    Function byteArrayToHexString(data() As Byte, spaceOctets As Boolean) As String
        Dim hexRep As String = ""
        For i As Integer = 0 To data.Length
            Dim c1 As String = hexOf((data(i) And 240) >> 4)
            Dim c2 As String = hexOf(data(i) And 15)
            hexRep = hexRep & c1 & c2 & If(spaceOctets, " ", "")
        Next i
        byteArrayToHexString = hexRep
    End Function

    Function hexOf(i As Integer) As String
        Dim returnString As String = ""
        If i < 10 Then
            returnString = "" & i
        Else
            Select Case i
                Case 10
                    returnString = "A"
                Case 11
                    returnString = "B"
                Case 12
                    returnString = "C"
                Case 13
                    returnString = "D"
                Case 14
                    returnString = "E"
                Case 15
                    returnString = "F"
            End Select
        End If
        hexOf = returnString
    End Function

    Function privateEncrypt(toEncrypt() As Byte, rsaParam As RSAParameters) As Byte()

        Dim bytes() As Byte
        bytes = rsaParam.Modulus
        Array.Reverse(bytes)
        ReDim Preserve bytes(bytes.Length)
        Dim modulus As New BigInteger(bytes)

        'ShowBytes("modulus", modulus.ToByteArray())
        Dim modLength As Integer = getSignificantLength(rsaParam.Modulus)
        bytes = rsaParam.D
        Array.Reverse(bytes)
        ReDim Preserve bytes(bytes.Length)
        Dim D As New BigInteger(bytes)
        'ShowBytes("D", D.ToByteArray())
        bytes = pkcs1PrivPad(toEncrypt, modLength)
        Array.Reverse(bytes)
        Dim data As New BigInteger(bytes)
        'ShowBytes("toEncrypt", toEncrypt)
        'ShowBytes("data", data.ToByteArray())
        Dim temp As BigInteger = BigInteger.ModPow(data, D, modulus)
        'ShowBytes("temp", temp.ToByteArray())
        bytes = temp.ToByteArray()
        Dim encrypted() As Byte = zeroPad(bytes, modLength)
        Array.Reverse(encrypted)
        'ShowBytes("encrypted", encrypted)
        privateEncrypt = encrypted
    End Function

    Function modPow(base As BigInteger, exponent As BigInteger, modulus As BigInteger) As BigInteger
        Dim result As BigInteger = 1
        'Console.WriteLine("Exponent: " & exponent.ToString())
        While exponent > 0
            If exponent Mod 2 = BigInteger.One Then
                result = (result * base) Mod modulus
            End If
            exponent = exponent >> 1
            base = (base * base) Mod modulus
        End While
        modPow = result
    End Function

    Function zeroPad(raw() As Byte, modLength As Integer) As Byte()
        Dim returnMe(0 To modLength - 1) As Byte

        Dim srcStart As Integer = Math.Max(raw.Length - modLength - 1, 0)
        Dim dstStart As Integer = Math.Max(0, modLength - raw.Length - 1)
        Dim length As Integer = Math.Max(modLength, raw.Length - 1)
        Console.WriteLine(raw.Length & " " & returnMe.Length & " " & modLength)
        Array.Copy(raw, srcStart, returnMe, dstStart, length)
        For i As Integer = 0 To (modLength - raw.Length - 1)
            returnMe(i) = 0
        Next i
        zeroPad = returnMe
    End Function

    Function getSignificantLength(raw() As Byte) As Integer
        Dim i As Integer
        While (raw(i) = 0)
            i = i + 1
        End While
        getSignificantLength = raw.Length - i
    End Function

    Function pkcs1PrivPad(raw() As Byte, modLength As Integer) As Byte()
        Dim os As MemoryStream = New MemoryStream()
        Dim padLength As Integer = (modLength - raw.Length)
        If padLength < 11 Then Return raw
        os.WriteByte(1)
        For i As Integer = 2 To padLength - 2
            os.WriteByte(255)
        Next i
        os.WriteByte(0)
        os.Write(raw, 0, raw.Length)
        Dim temp() As Byte = os.ToArray()
        pkcs1PrivPad = temp
    End Function

    Function DecodeRSAPrivateKey(privKey() As Byte) As RSAParameters
        Dim MODULUS(), E(), D(), P(), Q(), DP(), DQ(), IQ() As Byte

        Dim mem As MemoryStream = New MemoryStream(privKey)
        Dim binr As BinaryReader = New BinaryReader(mem)
        Dim RSAparams As RSAParameters = New RSAParameters()

        Dim bt As Byte = 0
        Dim twobytes As UInt16 = 0
        Dim elems As Integer

        'Try
        twobytes = binr.ReadUInt16()
        If twobytes = 33072 Then
            binr.ReadByte()
        ElseIf twobytes = 33328 Then
            binr.ReadInt16()
        Else
            Return RSAparams
        End If
        twobytes = binr.ReadUInt16()
        If twobytes <> 258 Then Return RSAparams
        bt = binr.ReadByte()
        If bt <> 0 Then Return RSAparams

        elems = getIntegerSize(binr)
        MODULUS = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        E = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        D = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        P = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        Q = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        DP = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        DQ = binr.ReadBytes(elems)

        elems = getIntegerSize(binr)
        IQ = binr.ReadBytes(elems)

        RSAparams.Modulus = MODULUS
        RSAparams.D = D
        RSAparams.Exponent = E
        RSAparams.P = P
        RSAparams.Q = Q
        RSAparams.DP = DP
        RSAparams.DQ = DQ
        RSAparams.InverseQ = IQ
        ''Catch ex As Exception
        ''Return RSAparams
        ''Finally
        binr.Close()
        ''End Try
        DecodeRSAPrivateKey = RSAparams
    End Function

    Function getIntegerSize(binr As BinaryReader) As Integer
        Dim bt As Byte = 0
        Dim lowbyte As Byte = 0
        Dim highbyte As Byte = 0
        Dim count As Integer = 0
        bt = binr.ReadByte()
        If bt <> 2 Then Return 0
        bt = binr.ReadByte()
        If bt = 129 Then
            count = binr.ReadByte()
        Else
            If bt = 130 Then
                highbyte = binr.ReadByte()
                lowbyte = binr.ReadByte()
                Dim modint() As Byte = {lowbyte, highbyte, 0, 0}
                count = BitConverter.ToInt32(modint, 0)
            Else
                count = bt
            End If
        End If
        While binr.ReadByte() = 0
            count = count - 1
        End While
        binr.BaseStream.Seek(-1, SeekOrigin.Current)
        getIntegerSize = count
    End Function

    Sub ShowBytes(info As String, data() As Byte)
        Console.WriteLine("{0}  [{1} bytes]", info, data.Length)
        For i As Integer = 1 To data.Length
            Console.Write("{0:X2}  ", data(i - 1))
            If i Mod 16 = 0 Then Console.WriteLine()
        Next i
        Console.WriteLine(vbCrLf & vbCrLf)
    End Sub

End Module

No comments:

Post a Comment