Moin,
ich zeige euch nun eine simple Methode um den Netzwerkverkehr eurer Server<->Client-Anwendung zu verschlüsseln.
Ich gehe dabei als Basis auf folgenden Thread ein:
Multiserver (TCP)
Wir fügen erstmal dem Server und dem Client-Projekt ein Modul namens "Crypt.vb" hinzu. Dieses brauchen beide Projekte.
Der Code ist nicht von mir, es handelt sich hierbei um die SHA256-Verschlüsselung.
Spoiler anzeigen
Fangen wir mit dem Server an..
Zu erst fügt ihr dem Struct "Connection" folgenden Wert hinzu:
Das fertige Struct könnte nun so aussehen:
Hier wird später dann der Key zum Ent- und Verschlüsseln für die jeweilige Connection gespeichert.
So, der Server soll nun beim Eingehen einer Verbindung einen Key für den Client aussuchen, welchen nur der Server und der spezifische Client kennen.
So, jetzt müssen wir als Server dem Client beim Joinen auch den Key mitteilen, dafür gehen wir in die Main-Methode und ersetzen
hiermit:
Ihr seht, ich habe im originalen Code
durch:
ersetzt.
Was passiert hier?
Sobald ein Client nun zum Server verbindet, wird dem Client ein Random Key zugewiesen, welcher zwischen 10 und 15 Zeichen lang ist.
Anschließend wird in diesen einen spezifischen Networkstream der Key gesendet, damit der Client diesen auch hat.
Andere Clients können diesen Key nicht bekommen. Als Standardpasswort für diesen einen Austausch ist hier "xored" gewählt, könnt ihr auch ändern.
Nach diesem Step hier werden alle weiteren Austausche zwischen Server und Client mit einem Random-Key passieren.
Die Funktion für den Random-Key ist folgende:
Folgende Funktion muss im Original-Code geändert werden, damit ihr als Server auch versteht was der einzelne Client von euch möchte:
Dort ersetzt ihr nämlich:
mit:
In tmp steckt hier jetzt der Text, welchen der Client an den Server gesendet hat, z.B. eine Chat-Nachricht.
Nun müsst ihr natürlich auch folgende Funktion im Original-Code anpassen:
Hier wurde ja bisher unverschlüsselt an alle Clients der Text in den Stream geschrieben.
Die neue Funktion lautet:
Ihr seht, dass hier jetzt an jede Connection das Paket gesendet wird und als Encryptionkey der Key aus dem Connection-Struct.
Ihr könnt jetzt ganz regulär die Funktion aufrufen:
und jeder Client wird den Text erhalten, aber außenstehende TCP-Clients können diese Nachricht nicht entziffern.
Gut, damit der Satz vor diesem hier aber auch stimmt, müssen wir natürlich auch im Client etwas verändern.
Kommen wir zum Client..
In der Funktion:
Müssen wir folgendes einfügen:
Der Server sendet wie ihr gesehen habt beim Connecten den Befehl /Key XYZRANDOM an den jeweiligen Client.
Hier lesen wir diesen Key aus und setzen ihn.
Folgende Deklaration muss natürlich vorher gemacht werden:
Hier muss das Passwort genau so sein wie im Server. Wie auch im Server gilt dieses Passwort nur für diesen einen Key-Austausch.
Das wars auch schon.
Vorher habt ihr in den Chat so geschrieben:
Das habe ich nun durch eine Funktion ersetzt:
So sendet ihr jetzt an den Server:
Die Nachricht wird mit eurem persönlichen Verschlüsselungskey gesendet.
Damit ihr jetzt als Client auch wisst, was der Server von euch will, ändert ihr noch folgende Funktion ab:
Dort ersetzt ihr nämlich:
mit:
Der Ablaufplan ist nun wie folgt:
Wie ihr noch vertraulicher Pakete vom Server an den Client sendet, erkläre ich im nächsten Tutorial. Da wirds dann darum gehen
einem spezifischen Client eine Nachricht zu senden, die gar nicht bei den fremden Clients ankommt, egal ob verschlüsselt oder nicht.
Bei Interesse kann ich gerne mal das Projekt von kevin89 nehmen, umbauen und hochladen, falls die Anleitung zu abstrakt klang.
Wenn ihr Fehler entdeckt, bitte melden. Ich habe es bisher nicht geschafft mit einem dritten TCP Client den Chatverlauf auszulesen.
xored
ich zeige euch nun eine simple Methode um den Netzwerkverkehr eurer Server<->Client-Anwendung zu verschlüsseln.
Ich gehe dabei als Basis auf folgenden Thread ein:
Multiserver (TCP)
Wir fügen erstmal dem Server und dem Client-Projekt ein Modul namens "Crypt.vb" hinzu. Dieses brauchen beide Projekte.
Der Code ist nicht von mir, es handelt sich hierbei um die SHA256-Verschlüsselung.
VB.NET-Quellcode
- Imports System.Security.Cryptography
- Imports System.Text
- Imports System.IO
- Module Crypt
- Public Function Encrypt(ByVal plainText As String, ByVal Pass As String) As String
- Try
- Dim saltValue As String = "bitteAendern"
- Dim hashAlgorithm As String = "SHA256"
- Dim passwordIterations As Integer = 2
- Dim initVector As String = "@1B2c3D4e5F6g7H8"
- Dim keySize As Integer = 256
- Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
- Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
- Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
- Dim password As New PasswordDeriveBytes(Pass, saltValueBytes, hashAlgorithm, passwordIterations)
- Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
- Dim symmetricKey As New RijndaelManaged()
- symmetricKey.Mode = CipherMode.CBC
- Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
- Dim memoryStream As New MemoryStream()
- Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
- cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
- cryptoStream.FlushFinalBlock()
- Dim cipherTextBytes As Byte() = memoryStream.ToArray()
- memoryStream.Close()
- cryptoStream.Close()
- Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
- Return cipherText
- Catch
- End Try
- End Function
- Public Function Decrypt(ByVal cipherText As String, ByVal Pass As String) As String
- Try
- Dim saltValue As String = "bitteAendern"
- Dim hashAlgorithm As String = "SHA256"
- Dim passwordIterations As Integer = 2
- Dim initVector As String = "@1B2c3D4e5F6g7H8"
- Dim keySize As Integer = 256
- Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
- Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
- Dim cipherTextBytes As Byte() = Convert.FromBase64String(cipherText)
- Dim password As New PasswordDeriveBytes(Pass, saltValueBytes, hashAlgorithm, passwordIterations)
- Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
- Dim symmetricKey As New RijndaelManaged()
- symmetricKey.Mode = CipherMode.CBC
- Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
- Dim memoryStream As New MemoryStream(cipherTextBytes)
- Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
- Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
- Dim decryptedByteCount As Integer
- Try
- decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
- Catch
- End Try
- memoryStream.Close()
- cryptoStream.Close()
- Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
- Return plainText
- Catch ex As Exception
- End Try
- End Function
- End Module
Fangen wir mit dem Server an..
Zu erst fügt ihr dem Struct "Connection" folgenden Wert hinzu:
Das fertige Struct könnte nun so aussehen:
Hier wird später dann der Key zum Ent- und Verschlüsseln für die jeweilige Connection gespeichert.
So, der Server soll nun beim Eingehen einer Verbindung einen Key für den Client aussuchen, welchen nur der Server und der spezifische Client kennen.
So, jetzt müssen wir als Server dem Client beim Joinen auch den Key mitteilen, dafür gehen wir in die Main-Methode und ersetzen
hiermit:
Ihr seht, ich habe im originalen Code
durch:
ersetzt.
Was passiert hier?
Sobald ein Client nun zum Server verbindet, wird dem Client ein Random Key zugewiesen, welcher zwischen 10 und 15 Zeichen lang ist.
Anschließend wird in diesen einen spezifischen Networkstream der Key gesendet, damit der Client diesen auch hat.
Andere Clients können diesen Key nicht bekommen. Als Standardpasswort für diesen einen Austausch ist hier "xored" gewählt, könnt ihr auch ändern.
Nach diesem Step hier werden alle weiteren Austausche zwischen Server und Client mit einem Random-Key passieren.
Die Funktion für den Random-Key ist folgende:
VB.NET-Quellcode
- Function RandomString(minCharacters As Integer, maxCharacters As Integer)
- Dim s As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
- Static r As New Random
- Dim chactersInString As Integer = r.Next(minCharacters, maxCharacters)
- Dim sb As New StringBuilder
- For i As Integer = 1 To chactersInString
- Dim idx As Integer = r.Next(0, s.Length)
- sb.Append(s.Substring(idx, 1))
- Next
- Return sb.ToString()
- End Function
Folgende Funktion muss im Original-Code geändert werden, damit ihr als Server auch versteht was der einzelne Client von euch möchte:
Dort ersetzt ihr nämlich:
mit:
In tmp steckt hier jetzt der Text, welchen der Client an den Server gesendet hat, z.B. eine Chat-Nachricht.
Nun müsst ihr natürlich auch folgende Funktion im Original-Code anpassen:
Hier wurde ja bisher unverschlüsselt an alle Clients der Text in den Stream geschrieben.
Die neue Funktion lautet:
Ihr seht, dass hier jetzt an jede Connection das Paket gesendet wird und als Encryptionkey der Key aus dem Connection-Struct.
Ihr könnt jetzt ganz regulär die Funktion aufrufen:
und jeder Client wird den Text erhalten, aber außenstehende TCP-Clients können diese Nachricht nicht entziffern.
Gut, damit der Satz vor diesem hier aber auch stimmt, müssen wir natürlich auch im Client etwas verändern.
Kommen wir zum Client..
In der Funktion:
Müssen wir folgendes einfügen:
Der Server sendet wie ihr gesehen habt beim Connecten den Befehl /Key XYZRANDOM an den jeweiligen Client.
Hier lesen wir diesen Key aus und setzen ihn.
Folgende Deklaration muss natürlich vorher gemacht werden:
Hier muss das Passwort genau so sein wie im Server. Wie auch im Server gilt dieses Passwort nur für diesen einen Key-Austausch.
Das wars auch schon.
Vorher habt ihr in den Chat so geschrieben:
Das habe ich nun durch eine Funktion ersetzt:
So sendet ihr jetzt an den Server:
Die Nachricht wird mit eurem persönlichen Verschlüsselungskey gesendet.
Damit ihr jetzt als Client auch wisst, was der Server von euch will, ändert ihr noch folgende Funktion ab:
Dort ersetzt ihr nämlich:
mit:
Der Ablaufplan ist nun wie folgt:
- Der Client connected zum Server
- Der Server denkt sich einen CryptKey aus und sendet dieses direkt in den Stream des Clients (Von außen nicht einsehbar)
- Der Client liest den Key aus und setzt diesen als globalen Key
- Der Client sendet nun Nachrichten an den Server verschlüsselt
- Der Server kann die Nachrichten entschlüsseln
- Der Server sendet Nachrichten an den Client auch verschlüsselt
Wie ihr noch vertraulicher Pakete vom Server an den Client sendet, erkläre ich im nächsten Tutorial. Da wirds dann darum gehen
einem spezifischen Client eine Nachricht zu senden, die gar nicht bei den fremden Clients ankommt, egal ob verschlüsselt oder nicht.
Bei Interesse kann ich gerne mal das Projekt von kevin89 nehmen, umbauen und hochladen, falls die Anleitung zu abstrakt klang.
Wenn ihr Fehler entdeckt, bitte melden. Ich habe es bisher nicht geschafft mit einem dritten TCP Client den Chatverlauf auszulesen.
xored