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
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