2012-04-02 22 views
2

Ich habe eine grundlegende tcp Client/Server-Setup in C# gehen. Ich versuche jetzt, die Daten hin und her zu verschlüsseln. Ich kann Daten vom Client an den Server senden, den Server einen Befehl ausführen lassen und dann versuchen, die Ergebnisse zurück an den Client zu senden. Ich kann die Daten von Client zu Server abrufen, und der Server führt den Befehl aus. Wenn der Server versucht, Ergebnisse zurück an den Client zu senden, erhalte ich eine Fehlermeldung auf dem Client, dass der Stream nicht lesbar ist. Unten sind relevante Codeteile.Client/Server, verschlüsselte Kommunikation

Server:

....... 
//Create an instance of TcpListener to listen for TCP connection. 
    TcpListener tcpListener = new TcpListener(IPAddress.Any, TcpPort); 
    try 
    { 
     while (true) 
     { 
      tcpListener.Start(); 
      //Accept the client if one is found. 
      TcpClient TCP = tcpListener.AcceptTcpClient(); 
      // Console.WriteLine("Client connected through TCP."); 

      //Create a network stream from the connection. 
      NetworkStream NetStream = TCP.GetStream(); 

      //Create a new instance of the RijndaelManaged class 
      // and decrypt the stream. 
      RijndaelManaged RMCrypto = new RijndaelManaged(); 


      //Create a CryptoStream, pass it the NetworkStream, decrypt with the Rijndael class using the key and IV. 
      CryptoStream CryptStream = new CryptoStream(NetStream,RMCrypto.CreateDecryptor(Key, IV),CryptoStreamMode.Read); 

      //Read the stream. 
      StreamReader SReader = new StreamReader(CryptStream); 

      //run the command received 
      string commandToRun = SReader.ReadToEnd(); 
      string commandOutput = runCommand(commandToRun); 
      Console.WriteLine("output is " + commandOutput); 
     //  SReader.Close(); 

      // now send results back 
      CryptoStream CStream_WRITE = new CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write); 

      if (CStream_WRITE.CanWrite) 
      { 
       //Create a StreamWriter for easy writing to the network stream. 
       StreamWriter SWriter2 = new StreamWriter(CStream_WRITE); 

       //Write to the stream. 
       SWriter2.Write(commandOutput, commandOutput.Length); 
       Console.WriteLine("writing {0} bytes back ", commandOutput.Length); 
       SWriter2.Flush(); 
       SWriter2.Close(); 
      } 

     //  CStream_WRITE.Close(); 
     //  NetStream.Close(); 
     //  TCP.Close(); 
       tcpListener.Stop(); 

     } // end while 
    } 
    //Catch any exceptions. 
    catch 
    { 
     Console.WriteLine("Server Failed"); 
    } 
} 

Und hier ist der Kunde: ....... Die fette Linie ist, wo ich eine Störung erhalte

 //Create a TCP connection to a listening TCP process. 

     TcpClient TCP = new TcpClient(serverName, TCPPORT); 

     //Create a network stream from the TCP connection. 
     NetworkStream NetStream = TCP.GetStream(); 

     //Create a new instance of the RijndaelManaged class 
     // and encrypt the stream. 
     RijndaelManaged RMCrypto = new RijndaelManaged(); 

     byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; 
     byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; 

     //Create a CryptoStream, pass it the NetworkStream, and encrypt 
     //it with the Rijndael class. 
     CryptoStream CryptStream = new CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write); 

     if (CryptStream.CanWrite) 
     { 
      //Create a StreamWriter for easy writing to the network stream. 
      StreamWriter SWriter = new StreamWriter(CryptStream); 

      //Write to the stream. 
      SWriter.WriteLine(theData); 
      SWriter.Flush(); 
      SWriter.Close(); 
     // CryptStream.Close(); 

      //Inform the user that the message was written to the stream. 
      Console.WriteLine("The message was sent."); 
     } 

     // get response 
     **CryptoStream CStreamREAD = new CryptoStream(NetStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read);** 
     if (CStreamREAD.CanRead) 
     { 
      Console.WriteLine("stream can read\n"); 
      StreamReader SReader = new StreamReader(CStreamREAD); 
      string commandResults = SReader.ReadToEnd(); 
      Console.WriteLine("receiving {0} bytes from server", commandResults.Length); 
      Console.WriteLine("results are " + commandResults) 
+0

Bitte immer die ** vollständige ** Fehlermeldung selbst enthalten. Oh, und willkommen ... –

Antwort

4

Die einfachste und bei weitem der Am sichersten ist es, ein bereits bestehendes Protokoll wie SSL zu implementieren. Sie können die Klasse SslStream verwenden, um Sicherheit und Serverauthentifizierung bereitzustellen, oder Sie können einfach zu WCF wechseln und sich überhaupt nicht um Streams kümmern. Here ist eine Frage zum Aktivieren von SSL für WCF. Wie für ein einfaches WCF-Tutorial gibt es Hunderte.

Rolling your own ist wahrscheinlich sehr unsicher und fehleranfällig.

+0

Guter Rat im Allgemeinen, aber das Poster scheint dies für "akademische" Zwecke zu tun ... –

+0

Außerdem ist es einfach keine Antwort auf die Frage, verwenden Sie Kommentare! –

+0

Ich hatte das gedacht, aber dann habe ich auch so viele Dinge gesehen, die "akademisch" in Produktionssoftware verwandeln, also kann man nie zu vorsichtig sein :) – mfanto

0

StreamWriter.close() schließt auch den zugrunde liegenden Stream, der CryptoStream schließt, der den zugrunde liegenden Socket nach API schließt.

Zumindest, das bin meine Vermutung als erfahrene Java-Entwickler :)