клиент / сервер, зашифрованные сообщения - PullRequest
2 голосов
/ 03 апреля 2012

У меня есть базовая настройка tcp клиент / сервер в c #. Я сейчас пытаюсь зашифровать данные, идущие туда-сюда. Я могу отправить данные с клиента на сервер, заставить сервер выполнить команду, а затем попытаться отправить результаты обратно клиенту. Я могу получить данные от клиента к серверу, и сервер выполняет команду. Когда сервер пытается отправить результаты обратно клиенту, я получаю сообщение об ошибке на клиенте, что поток не читается. Ниже приведены соответствующие части кода.

Сервер:

    .......
//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");
    }
}

А вот и клиент: ....... Жирная линия, где я получаю сообщение об ошибке

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

Ответы [ 2 ]

4 голосов
/ 03 апреля 2012

Самый простой и самый безопасный способ - использовать уже существующий протокол, такой как SSL. Вы можете использовать класс SslStream для обеспечения безопасности и проверки подлинности сервера, или вы можете просто переключиться на WCF и вообще не работать с потоками. Здесь - вопрос о том, как включить SSL для WCF. Что касается только основного учебника WCF, их сотни.

Свертывание собственного может быть очень небезопасным и подверженным ошибкам.

0 голосов
/ 03 апреля 2012

StreamWriter.close () также закрывает базовый поток, который закрывает CryptoStream, который закрывает базовый сокет согласно API.

По крайней мере, это мое предположение, как опытного разработчика Java:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...