leetupload
September 08, 2010, 06:23:02 pm *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Click here to get back to the Database!
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: 128-bit Encrypted Chat - VB.net  (Read 3210 times)
glj12
Administrator
[user]$ sudo su
*****
Posts: 373



View Profile WWW Email
« on: October 08, 2008, 04:06:26 pm »

Well, I finally wrote my own chat protocol (TCP client/server based) where it is twice encrypted. Here's how this convoluted piece works:

2 Keys, 1 per encrypt/decrypt method. Both are 27 rand(char)

Client sends encrypted 128-bit message
Server receives it and does the following (notice how I label them 1 and 2, those specify which one they are):
             Encrypt2( "extra string of data including the client name, etc." Decrypt1("encrypted1 message", "Key1"), "Key2")
Server sends the new encryption back to the clients, in order to be decrypted by Key2.

Still following? Good. That's about it. If anyone knows VB.net and wants to make it better, have at it once everything is posted. Comments are welcome.

Server

Code:
Imports System.Security.Cryptography
Imports System.IO

Imports System.Net.Sockets
Imports System.Text
Module Module1
    Dim clientsList As New Hashtable
    Sub Main()
        Dim serverSocket As New TcpListener(8888)
        Dim clientSocket As TcpClient
        Dim infiniteCounter As Integer
        Dim counter As Integer

        serverSocket.Start()
        msg("Glj12's 128-bit Secure Chat Server Started...")
        counter = 0
        infiniteCounter = 0
        For infiniteCounter = 1 To 2
            infiniteCounter = 1
            counter += 1
            clientSocket = serverSocket.AcceptTcpClient()

            Dim bytesFrom(10024) As Byte
            Dim dataFromClient As String

            Dim networkStream As NetworkStream = _
            clientSocket.GetStream()
            networkStream.Read(bytesFrom, 0, CInt(clientSocket.ReceiveBufferSize))
            dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom)
            dataFromClient = _
            dataFromClient.Substring(0, dataFromClient.IndexOf("$"))

            clientsList(dataFromClient) = clientSocket


            Dim tm As System.DateTime
            tm = Now
            broadcast("(" + Now + ")" + "  " + dataFromClient + " Joined ", dataFromClient, False)

            msg(dataFromClient + " Joined chat room ")
            Dim client As New handleClinet
            client.startClient(clientSocket, dataFromClient, clientsList)
        Next

        clientSocket.Close()
        serverSocket.Stop()
        msg("exit")
        Console.ReadLine()
    End Sub

    Sub msg(ByVal mesg As String)
        mesg.Trim()
        Dim tm As System.DateTime
        tm = Now
        Console.WriteLine("(" + Now + ")" + " >> " + mesg)
    End Sub
    Private Sub broadcast(ByVal msg As String, _
    ByVal uName As String, ByVal flag As Boolean)
        Dim Item As DictionaryEntry
        For Each Item In clientsList
            Dim broadcastSocket As TcpClient
            broadcastSocket = CType(Item.Value, TcpClient)
            Dim broadcastStream As NetworkStream = _
                    broadcastSocket.GetStream()
            Dim broadcastBytes As [Byte]()

            Dim tm As System.DateTime
            tm = Now
            Dim time1 As String = DateTime.Now.ToShortTimeString()

            If flag = True Then
                ' Notice that I am decrypting the original encryption... then encrypting it again with the second one. Sheesh!
                broadcastBytes = Encoding.ASCII.GetBytes(EncryptString128Bit("(" + time1 + ")" + "  " + uName + " : " + DecryptString128Bit(msg, "Key1"), "Key2")) 'This appears in the client window (the format for sending text with the user's name)
            Else
                broadcastBytes = Encoding.ASCII.GetBytes(EncryptString128Bit("(" + time1 + ")" + "  " + uName + " : " + DecryptString128Bit(msg, "Key1"), "Key2"))
            End If

            broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length)
            broadcastStream.Flush()
        Next
    End Sub

    Public Class handleClinet
        Dim clientSocket As TcpClient
        Dim clNo As String
        Dim clientsList As Hashtable

        Public Sub startClient(ByVal inClientSocket As TcpClient, _
        ByVal clineNo As String, ByVal cList As Hashtable)
            Me.clientSocket = inClientSocket
            Me.clNo = clineNo
            Me.clientsList = cList
            Dim ctThread As Threading.Thread = New Threading.Thread(AddressOf doChat)
            ctThread.Start()
        End Sub

        Private Sub doChat()
            Dim infiniteCounter As Integer
            Dim requestCount As Integer
            Dim bytesFrom(10024) As Byte
            Dim dataFromClient As String
            Dim sendBytes As [Byte]()
            Dim serverResponse As String
            Dim rCount As String
            requestCount = 0
            For infiniteCounter = 1 To 2
                infiniteCounter = 1
                Try
                    requestCount = requestCount + 1
                    Dim networkStream As NetworkStream = _
                            clientSocket.GetStream()
                    networkStream.Read(bytesFrom, 0, CInt(clientSocket.ReceiveBufferSize))
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom)
                    dataFromClient = _
                        dataFromClient.Substring(0, dataFromClient.IndexOf("$"))

                    msg("From client - " + clNo + " : " + dataFromClient)
                    rCount = Convert.ToString(requestCount)

                    broadcast(dataFromClient, clNo, True)
                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
            Next
        End Sub

    End Class


    'Byte vector required for Rijndael.  This is randomly generated and recommended you change it on a per-application basis.
    'It is 16 bytes.
    Private bytIV() As Byte = {121, 241, 10, 1, 132, 74, 11, 39, 255, 91, 45, 78, 14, 211, 22, 62}

    'Character to pad keys with to make them at least intMinKeySize.
    Private Const chrKeyFill As Char = CType("X", Char)

    'String to display on error for functions that return strings. {0} is Exception.Message.
    Private Const strTextErrorString As String = "has joined the room (or this msg failed to decrypt)" '"#ERROR - {0}"

    'Min size in bytes of randomly generated salt.
    Private Const intMinSalt As Integer = 4

    'Max size in bytes of randomly generated salt.
    Private Const intMaxSalt As Integer = 8

    'Size in bytes of Hash result.  MD5 returns a 128 bit hash.
    Private Const intHashSize As Integer = 16

    'Size in bytes of the key length.  Rijndael takes either a 128, 192, or 256 bit key.  
    'If it is under this, pad with chrKeyFill. If it is over this, truncate to the length.
    Private Const intKeySize As Integer = 32

    'Encrypt a String with Rijndael symmetric encryption.
    Public Function EncryptString128Bit(ByVal strPlainText As String, ByVal strKey As String) As String
        Try
            Dim bytPlainText() As Byte
            Dim bytKey() As Byte
            Dim bytEncoded() As Byte
            Dim objMemoryStream As New MemoryStream
            Dim objRijndaelManaged As New RijndaelManaged

            strPlainText = strPlainText.Replace(vbNullChar, String.Empty)

            bytPlainText = Encoding.UTF8.GetBytes(strPlainText)
            bytKey = ConvertKeyToBytes(strKey)

            Dim objCryptoStream As New CryptoStream(objMemoryStream, _
                objRijndaelManaged.CreateEncryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)

            objCryptoStream.Write(bytPlainText, 0, bytPlainText.Length)
            objCryptoStream.FlushFinalBlock()

            bytEncoded = objMemoryStream.ToArray
            objMemoryStream.Close()
            objCryptoStream.Close()

            Return Convert.ToBase64String(bytEncoded)
        Catch ex As Exception
            Return String.Format(strTextErrorString)
            ' Return String.Format(strTextErrorString, ex.Message)
        End Try
    End Function

    'Decrypt a String with Rijndael symmetric encryption.
    Public Function DecryptString128Bit(ByVal strCryptText As String, ByVal strKey As String) As String
        Try
            Dim bytCryptText() As Byte
            Dim bytKey() As Byte

            Dim objRijndaelManaged As New RijndaelManaged

            bytCryptText = Convert.FromBase64String(strCryptText)
            bytKey = ConvertKeyToBytes(strKey)

            Dim bytTemp(bytCryptText.Length) As Byte
            Dim objMemoryStream As New MemoryStream(bytCryptText)

            Dim objCryptoStream As New CryptoStream(objMemoryStream, _
                objRijndaelManaged.CreateDecryptor(bytKey, bytIV), _
                CryptoStreamMode.Read)

            objCryptoStream.Read(bytTemp, 0, bytTemp.Length)

            objMemoryStream.Close()
            objCryptoStream.Close()

            Return Encoding.UTF8.GetString(bytTemp).Replace(vbNullChar, String.Empty)

        Catch ex As Exception
            Return String.Format(strTextErrorString, ex.Message)
        End Try

    End Function

    'Compute an MD5 hash code from a string and append any salt-bytes used/generated to the end.
    Public Function ComputeMD5Hash(ByVal strPlainText As String, Optional ByVal bytSalt() As Byte = Nothing) As String
        Try
            Dim bytPlainText As Byte() = Encoding.UTF8.GetBytes(strPlainText)
            Dim hash As HashAlgorithm = New MD5CryptoServiceProvider()

            If bytSalt Is Nothing Then
                Dim rand As New Random
                Dim intSaltSize As Integer = rand.Next(intMinSalt, intMaxSalt)

                bytSalt = New Byte(intSaltSize - 1) {}

                Dim rng As New RNGCryptoServiceProvider
                rng.GetNonZeroBytes(bytSalt)
            End If

            Dim bytPlainTextWithSalt() As Byte = New Byte(bytPlainText.Length + bytSalt.Length - 1) {}

            bytPlainTextWithSalt = ConcatBytes(bytPlainText, bytSalt)

            Dim bytHash As Byte() = hash.ComputeHash(bytPlainTextWithSalt)
            Dim bytHashWithSalt() As Byte = New Byte(bytHash.Length + bytSalt.Length - 1) {}

            bytHashWithSalt = ConcatBytes(bytHash, bytSalt)

            Return Convert.ToBase64String(bytHashWithSalt)
        Catch ex As Exception
            Return String.Format(strTextErrorString, ex.Message)
        End Try
    End Function

    'Verify a string against a hash generated with the ComputeMD5Hash function above.
    Public Function VerifyHash(ByVal strPlainText As String, ByVal strHashValue As String) As Boolean
        Try
            Dim bytWithSalt As Byte() = Convert.FromBase64String(strHashValue)

            If bytWithSalt.Length < intHashSize Then Return False

            Dim bytSalt() As Byte = New Byte(bytWithSalt.Length - intHashSize - 1) {}

            Array.Copy(bytWithSalt, intHashSize, bytSalt, 0, bytWithSalt.Length - intHashSize)

            Dim strExpectedHashString As String = ComputeMD5Hash(strPlainText, bytSalt)

            Return strHashValue.Equals(strExpectedHashString)
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    'Simple function to concatenate two byte arrays.
    Private Function ConcatBytes(ByVal bytA() As Byte, ByVal bytB() As Byte) As Byte()
        Try
            Dim bytX() As Byte = New Byte(((bytA.Length + bytB.Length)) - 1) {}

            Array.Copy(bytA, bytX, bytA.Length)
            Array.Copy(bytB, 0, bytX, bytA.Length, bytB.Length)

            Return bytX
        Catch ex As Exception
            Return Nothing
        End Try

    End Function

    'A function to convert a string into a 32 byte key.
    Private Function ConvertKeyToBytes(ByVal strKey As String) As Byte()
        Try
            Dim intLength As Integer = strKey.Length

            If intLength < intKeySize Then
                strKey &= Strings.StrDup(intKeySize - intLength, chrKeyFill)
            Else
                strKey = strKey.Substring(0, intKeySize)
            End If

            Return Encoding.UTF8.GetBytes(strKey)
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    ' end decryption method

End Module
« Last Edit: October 08, 2008, 06:56:45 pm by glj12 » Logged

Support leetupload.com!
glj12
Administrator
[user]$ sudo su
*****
Posts: 373



View Profile WWW Email
« Reply #1 on: October 08, 2008, 06:56:56 pm »

Client

Code:
Imports System.Security.Cryptography
Imports System.IO

Imports System.Net.Sockets
Imports System.Text
Public Class Form1
    Dim clientSocket As New System.Net.Sockets.TcpClient()
    Dim serverStream As NetworkStream
    Dim readData As String
    Dim infiniteCounter As Integer

    ' implemented enter feature

    Private Sub TextBox2_KeyDown(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox2.KeyDown

        If e.KeyCode = Keys.Enter Then
            Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes(EncryptString128Bit(TextBox2.Text, "R*^&#*(FBNnA&O#rhO@Q*($nfds") + "$") ' R*^&#*(FBNnA&O#rhO@Q*($nfds = 1st key
            serverStream.Write(outStream, 0, outStream.Length)
            serverStream.Flush()
            TextBox2.Text = ""
        End If

    End Sub

    Private Sub TextBox2_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles RichTextBox1.KeyPress

    End Sub

    Private Sub msg()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf msg))
        Else
            RichTextBox1.Text = RichTextBox1.Text + Environment.NewLine + readData
        End If
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button2.Click
        readData = "Conected to Glj12's Insecure Chat Server ..."
        msg()
        clientSocket.Connect(TextBox4.Text, 8888)
        'Label1.Text = "Client Socket Program - Server Connected ..."
        serverStream = clientSocket.GetStream()

        Dim outStream As Byte() = _
        System.Text.Encoding.ASCII.GetBytes(TextBox3.Text + "$")
        serverStream.Write(outStream, 0, outStream.Length)
        serverStream.Flush()

        Dim ctThread As Threading.Thread = New Threading.Thread(AddressOf getMessage)
        ctThread.Start()
    End Sub

    Private Sub getMessage()
        For infiniteCounter = 1 To 2
            infiniteCounter = 1
            serverStream = clientSocket.GetStream()
            Dim buffSize As Integer
            Dim inStream(10024) As Byte
            buffSize = clientSocket.ReceiveBufferSize
            serverStream.Read(inStream, 0, buffSize)
            Dim returndata As String = _
            System.Text.Encoding.ASCII.GetString(inStream)
            readData = "" + returndata

            RichTextBox2.Text = readData ' Also note that there is RichTextBox2... this needs to remain visible. I don't know why, just do it. This is where the value is stored, then trnaslated and appended to RichTextBox
            RichTextBox1.Text = RichTextBox1.Text + Environment.NewLine + DecryptString128Bit(RichTextBox2.Text, "Key2")
            'DecryptString128Bit(readData, "Key2")
            'msg()
            RichTextBox2.Text = ""
        Next
    End Sub

    Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub RichTextBox1_LinkClicked(ByVal sender As Object, ByVal e As System.Windows.Forms.LinkClickedEventArgs) Handles RichTextBox1.LinkClicked
        System.Diagnostics.Process.Start(e.LinkText)
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        On Error Resume Next
        RichTextBox1.SelectionLength = 0
        RichTextBox1.SelectionStart = RichTextBox1.Text.Length
        RichTextBox1.ScrollToCaret()
    End Sub

    Private Sub RichTextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RichTextBox1.TextChanged

    End Sub


    'Byte vector required for Rijndael.  This is randomly generated and recommended you change it on a per-application basis.
    'It is 16 bytes.
    Private bytIV() As Byte = {121, 241, 10, 1, 132, 74, 11, 39, 255, 91, 45, 78, 14, 211, 22, 62}

    'Character to pad keys with to make them at least intMinKeySize.
    Private Const chrKeyFill As Char = CType("X", Char)

    'String to display on error for functions that return strings. {0} is Exception.Message.
    Private Const strTextErrorString As String = "has joined the room (or this msg failed to decrypt)" '"#ERROR - {0}"

    'Min size in bytes of randomly generated salt.
    Private Const intMinSalt As Integer = 4

    'Max size in bytes of randomly generated salt.
    Private Const intMaxSalt As Integer = 8

    'Size in bytes of Hash result.  MD5 returns a 128 bit hash.
    Private Const intHashSize As Integer = 16

    'Size in bytes of the key length.  Rijndael takes either a 128, 192, or 256 bit key. 
    'If it is under this, pad with chrKeyFill. If it is over this, truncate to the length.
    Private Const intKeySize As Integer = 32

    'Encrypt a String with Rijndael symmetric encryption.
    Public Function EncryptString128Bit(ByVal strPlainText As String, ByVal strKey As String) As String
        Try
            Dim bytPlainText() As Byte
            Dim bytKey() As Byte
            Dim bytEncoded() As Byte
            Dim objMemoryStream As New MemoryStream
            Dim objRijndaelManaged As New RijndaelManaged

            strPlainText = strPlainText.Replace(vbNullChar, String.Empty)

            bytPlainText = Encoding.UTF8.GetBytes(strPlainText)
            bytKey = ConvertKeyToBytes(strKey)

            Dim objCryptoStream As New CryptoStream(objMemoryStream, _
                objRijndaelManaged.CreateEncryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)

            objCryptoStream.Write(bytPlainText, 0, bytPlainText.Length)
            objCryptoStream.FlushFinalBlock()

            bytEncoded = objMemoryStream.ToArray
            objMemoryStream.Close()
            objCryptoStream.Close()

            Return Convert.ToBase64String(bytEncoded)
        Catch ex As Exception
            Return String.Format(strTextErrorString)
            ' Return String.Format(strTextErrorString, ex.Message)
        End Try
    End Function

    'Decrypt a String with Rijndael symmetric encryption.
    Public Function DecryptString128Bit(ByVal strCryptText As String, ByVal strKey As String) As String
        Try
            Dim bytCryptText() As Byte
            Dim bytKey() As Byte

            Dim objRijndaelManaged As New RijndaelManaged

            bytCryptText = Convert.FromBase64String(strCryptText)
            bytKey = ConvertKeyToBytes(strKey)

            Dim bytTemp(bytCryptText.Length) As Byte
            Dim objMemoryStream As New MemoryStream(bytCryptText)

            Dim objCryptoStream As New CryptoStream(objMemoryStream, _
                objRijndaelManaged.CreateDecryptor(bytKey, bytIV), _
                CryptoStreamMode.Read)

            objCryptoStream.Read(bytTemp, 0, bytTemp.Length)

            objMemoryStream.Close()
            objCryptoStream.Close()

            Return Encoding.UTF8.GetString(bytTemp).Replace(vbNullChar, String.Empty)

        Catch ex As Exception
            Return String.Format(strTextErrorString, ex.Message)
        End Try

    End Function

    'Compute an MD5 hash code from a string and append any salt-bytes used/generated to the end.
    Public Function ComputeMD5Hash(ByVal strPlainText As String, Optional ByVal bytSalt() As Byte = Nothing) As String
        Try
            Dim bytPlainText As Byte() = Encoding.UTF8.GetBytes(strPlainText)
            Dim hash As HashAlgorithm = New MD5CryptoServiceProvider()

            If bytSalt Is Nothing Then
                Dim rand As New Random
                Dim intSaltSize As Integer = rand.Next(intMinSalt, intMaxSalt)

                bytSalt = New Byte(intSaltSize - 1) {}

                Dim rng As New RNGCryptoServiceProvider
                rng.GetNonZeroBytes(bytSalt)
            End If

            Dim bytPlainTextWithSalt() As Byte = New Byte(bytPlainText.Length + bytSalt.Length - 1) {}

            bytPlainTextWithSalt = ConcatBytes(bytPlainText, bytSalt)

            Dim bytHash As Byte() = hash.ComputeHash(bytPlainTextWithSalt)
            Dim bytHashWithSalt() As Byte = New Byte(bytHash.Length + bytSalt.Length - 1) {}

            bytHashWithSalt = ConcatBytes(bytHash, bytSalt)

            Return Convert.ToBase64String(bytHashWithSalt)
        Catch ex As Exception
            Return String.Format(strTextErrorString, ex.Message)
        End Try
    End Function

    'Verify a string against a hash generated with the ComputeMD5Hash function above.
    Public Function VerifyHash(ByVal strPlainText As String, ByVal strHashValue As String) As Boolean
        Try
            Dim bytWithSalt As Byte() = Convert.FromBase64String(strHashValue)

            If bytWithSalt.Length < intHashSize Then Return False

            Dim bytSalt() As Byte = New Byte(bytWithSalt.Length - intHashSize - 1) {}

            Array.Copy(bytWithSalt, intHashSize, bytSalt, 0, bytWithSalt.Length - intHashSize)

            Dim strExpectedHashString As String = ComputeMD5Hash(strPlainText, bytSalt)

            Return strHashValue.Equals(strExpectedHashString)
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    'Simple function to concatenate two byte arrays.
    Private Function ConcatBytes(ByVal bytA() As Byte, ByVal bytB() As Byte) As Byte()
        Try
            Dim bytX() As Byte = New Byte(((bytA.Length + bytB.Length)) - 1) {}

            Array.Copy(bytA, bytX, bytA.Length)
            Array.Copy(bytB, 0, bytX, bytA.Length, bytB.Length)

            Return bytX
        Catch ex As Exception
            Return Nothing
        End Try

    End Function

    'A function to convert a string into a 32 byte key.
    Private Function ConvertKeyToBytes(ByVal strKey As String) As Byte()
        Try
            Dim intLength As Integer = strKey.Length

            If intLength < intKeySize Then
                strKey &= Strings.StrDup(intKeySize - intLength, chrKeyFill)
            Else
                strKey = strKey.Substring(0, intKeySize)
            End If

            Return Encoding.UTF8.GetBytes(strKey)
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    ' end decryption method

End Class
Logged

Support leetupload.com!
0cool
leet options user
**
Posts: 93



View Profile
« Reply #2 on: October 08, 2008, 10:54:11 pm »

Dude, that is really 1337.  How long have you been programming? When most people say they can code it means they understand the  syntax. You really know how.

I've been learning to program for about a year now. Mostly PHP, Javascript, VB .Net, and Pascal (to me Delphi/free pascal seem like a good thing for a non-professional to make native utilities and security tools). I'm really more of a network guy though.


« Last Edit: October 08, 2008, 11:04:24 pm by 0cool » Logged
glj12
Administrator
[user]$ sudo su
*****
Posts: 373



View Profile WWW Email
« Reply #3 on: October 09, 2008, 04:27:44 am »

I really appreciate the comment, and am quite flattered. Let's see here... I think I have been programming since I was 12 or 13 (however old I would have been in 7th grade), and my first language then was VB4 (lol). From there, I went onto bigger and better things (more VB, haha), scripting, C, MATLab, Scheme, and Java.

So yeah, that's my history with it. And Delphi, wow, that's interesting. I'd love to take a look at that sometime.

If you (or anyone else) ever try this code out, let me know if you find any bugs (security wise is what I'll care about since I am a network guy too Wink).

Cheers!
-leetupload
Logged

Support leetupload.com!
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.10 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!