Научно-образовательный IT-форум при КНИТУ-КАИ

Объявление

Семинар на тему «Восстановление кривых изменений вегетационных индексов по данным космической съемки (на примере индекса NDVI)» Д.А. Колесов (NextGIS). Дата и время: 24.11.2017 в 15.00; адрес: г.Казань, ул. Б.Красная, д.55, ауд. 428.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Научно-образовательный IT-форум при КНИТУ-КАИ » Задачи и вопросы » [+] Применение NetworkStream, CryptoStream, StreamWriter/StreamReader


[+] Применение NetworkStream, CryptoStream, StreamWriter/StreamReader

Сообщений 1 страница 10 из 16

1

Сервер:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;

namespace Server
{
    static class Program
    {

        static void Main(string[] args)
        {
            SymmetricAlgorithm des = new DESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes("12345678");
            des.IV = Encoding.ASCII.GetBytes("12345678");
            ICryptoTransform decrypt = des.CreateDecryptor();

            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"),5001);
            listener.Start();
            TcpClient tc = listener.AcceptTcpClient();
            NetworkStream stm = tc.GetStream();
            CryptoStream cryptostream = new CryptoStream(stm, decrypt, CryptoStreamMode.Read);
            StreamReader r = new StreamReader(stm);
            string str = r.ReadLine();
            Console.WriteLine("Зашифрованные данные: " + str);
            Console.WriteLine("Расшифрованные данные: " + Decrypt(str));
        }

        public static string Decrypt(this string text)
        {
            SymmetricAlgorithm algorithm = DES.Create();
            ICryptoTransform transform = algorithm.CreateDecryptor(Encoding.ASCII.GetBytes("12345678"), Encoding.ASCII.GetBytes("12345678"));
            byte[] inputbuffer = Encoding.UTF8.GetBytes(text);
            byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
            return Encoding.UTF8.GetString(outputBuffer);
        }

    }
}


Клиент:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                SymmetricAlgorithm des = new DESCryptoServiceProvider();
                des.Key = Encoding.ASCII.GetBytes("12345678");
                des.IV = Encoding.ASCII.GetBytes("12345678");
                ICryptoTransform encrypt = des.CreateEncryptor();

                TcpClient client = new TcpClient();
                client.Connect("localhost", 5001);
                NetworkStream stm = client.GetStream();
                CryptoStream cryptostream = new CryptoStream(stm, encrypt, CryptoStreamMode.Write);
                StreamWriter w = new StreamWriter(cryptostream);
                w.WriteLine("Hello world!");
                w.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.WriteLine("Server has probably not started.");
            }
        }
    }
}


Причина ошибки вроде бы понятна, но если подогнать данные под нужную длину, то получаем сообщение "Плохие данные". В чем причина?

https://bitbucket.org/landwatersun/forum/downloads/201609281554.png

http://forumfiles.ru/files/000c/4b/84/26892.jpg Решение

2

Возможно стоит использовать следующее решение для сервера

Код:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
namespace Server
{
    static class Program
    {
        static void Main(string[] args)
        {
            SymmetricAlgorithm des = new DESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes("12345678");
            des.IV = Encoding.ASCII.GetBytes("12345678");
            ICryptoTransform decrypt = des.CreateDecryptor();
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"),5001);
            listener.Start();
            TcpClient tc = listener.AcceptTcpClient();
            NetworkStream stm = tc.GetStream();
            CryptoStream cryptostream = new CryptoStream(stm, decrypt, CryptoStreamMode.Read);
            StreamReader r = new StreamReader(cryptostream);
            string str = r.ReadLine();
            Console.WriteLine("Расшифрованные данные: " + str);
            System.Console.Read();
        }
    }
}

3

Андрей (AnTimerlan) написал(а):

Возможно стоит использовать следующее решение для сервера

А в чем заключается решение задачи? :) На стороне сервера в консоли должны отображаться зашифрованный и расшифрованный тексты.

4

Окей. Встречный вопрос. Зачем нам зашифрованные данные?

В данный момент на сервере поднимается TcpClient, внутри которого поднимается CryptoStream. Когда мы читаем строку которую передает CryptoStream, то вероятнее всего захватываем и побочные управляющие символы или данные, поэтому при декодировании в лоб, расшифровать строку не получается.

Для шифровании и передачи данных(с возможностью их чтения), я считаю, что лучше использовать прямое кодирование в DES с помощью System.Security.Cryptography.DES qps.ru/oXQb4 (готовые функции EncryptStringToBytes и DecryptStringFromBytes) и передачу через TCP на сервер. Но к чему такие трудности?

5

Код сервера.

Пища для размышления:

Код:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
namespace Server {
    static class Program {
        static void Main(string[] args)
        {
            SymmetricAlgorithm des = new DESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes("12345678");
            des.IV = Encoding.ASCII.GetBytes("12345678");
            ICryptoTransform decrypt = des.CreateDecryptor();
            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 5001);
            listener.Start();
            TcpClient tc = listener.AcceptTcpClient();
            NetworkStream stm = tc.GetStream();
            CryptoStream cryptostream = new CryptoStream(stm, decrypt, CryptoStreamMode.Read);
            StreamReader r = new StreamReader(stm);
            string str = r.ReadLine();
            Console.WriteLine("Зашифрованные данные клиента: " + str);
            
            string text = "Hello world!";

            byte[] codingString = EncryptByte(text);

            text = EncryptString(text);

            Console.WriteLine("Зашифрованные данные сервера: " + text);

            Console.WriteLine("Расшифрованные данные сервера: " + Decrypt(codingString));
            Console.Read();
        }
        public static string EncryptString(string text)
        {
            SymmetricAlgorithm algorithm = DES.Create();
            ICryptoTransform transform = algorithm.CreateEncryptor(Encoding.ASCII.GetBytes("12345678"), Encoding.ASCII.GetBytes("12345678"));
            byte[] inputbuffer = Encoding.ASCII.GetBytes(text);
            byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
            return Encoding.ASCII.GetString(outputBuffer);
        }
        public static byte[] EncryptByte(string text)
        {
            SymmetricAlgorithm algorithm = DES.Create();
            ICryptoTransform transform = algorithm.CreateEncryptor(Encoding.ASCII.GetBytes("12345678"), Encoding.ASCII.GetBytes("12345678"));
            byte[] inputbuffer = Encoding.ASCII.GetBytes(text);
            byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
            return outputBuffer;
        }
        public static string Decrypt(byte[] bufer)
        {
            SymmetricAlgorithm algorithm = DES.Create();
            ICryptoTransform transform = algorithm.CreateDecryptor(Encoding.ASCII.GetBytes("12345678"), Encoding.ASCII.GetBytes("12345678"));
            byte[] inputbuffer = bufer;
            byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
            return Encoding.ASCII.GetString(outputBuffer);
        }
    }
}

6

Андрей (AnTimerlan) написал(а):

вероятнее всего захватываем и побочные управляющие символы или данные

Вот именно.

Андрей (AnTimerlan) написал(а):

Для шифровании и передачи данных(с возможностью их чтения), я считаю, что лучше использовать прямое кодирование в DES с помощью System.Security.Cryptography.DES qps.ru/oXQb4 (готовые функции EncryptStringToBytes и DecryptStringFromBytes) и передачу через TCP на сервер. Но к чему такие трудности?

Андрей, на самом деле не вызывает трудностей написание рабочего кода с передачей байтов напрямую без сторонних классов разновидностей Stream, подобный код уже имеется см. [+] Реализация шифрованного канала  Однако, в рамках данной темы очень хочется разобраться, каким образом отбросить управляющие символы или обойти прочие тонкости преобразований.

7

Вопрос «Зачем?» остается открытым)

8

Андрей (AnTimerlan) написал(а):

Вопрос «Зачем?» остается открытым)

Исключительно в учебных целях.

9

Код:
            CryptoStream cryptostream = new CryptoStream(stm, decrypt, CryptoStreamMode.Read);
            StreamReader r = new StreamReader(stm);
            string str = r.ReadLine();


CryptoStream - поток байтов. При чтении из него методом ReadLine() можно натолкнуться на символ '\n'. В этом случае часть байтов (после '\n') считана не будет, поэтому здесь нужно воспользоваться методом ReadToEnd();

10

Еще один момент: байты, преобразованные в строку методом Encoding.UTF8.GetString() не могут быть преобразованы обратно в тот же набор байтов, т.е. этот метод портит данные :)

Рабочий код сервера:

Код:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;

namespace Server
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 5001);
            listener.Start();
            var tc = listener.AcceptTcpClient();
            var stm = tc.GetStream();
            var bytes = new List<byte>();
            var buffer = new byte[1024];
            byte[] readedBytes;
            var readedCount = -1;

            while ((readedCount = stm.Read(buffer, 0, buffer.Length)) > 0)
            {
                if (readedCount != buffer.Length)
                {
                    readedBytes = new byte[readedCount];
                    Array.Copy(buffer, readedBytes, readedCount);
                }
                else
                {
                    readedBytes = buffer;
                }
                bytes.AddRange(readedBytes);
            }

            var resultBytes = bytes.ToArray();
            bytes.Clear();

            var str = Encoding.UTF8.GetString(resultBytes);

            Console.WriteLine("Зашифрованные данные: " + str);
            Console.WriteLine("Расшифрованные данные: " + Decrypt(resultBytes));
        }

        public static string Decrypt(this byte[] bytes)
        {
            SymmetricAlgorithm des = new DESCryptoServiceProvider
            {
                Key = Encoding.ASCII.GetBytes("12345678"),
                IV = Encoding.ASCII.GetBytes("12345678")
            };
            var transform = des.CreateDecryptor();
            var outputBuffer = transform.TransformFinalBlock(bytes, 0, bytes.Length);
            return Encoding.UTF8.GetString(outputBuffer);
        }
    }
}

Вы здесь » Научно-образовательный IT-форум при КНИТУ-КАИ » Задачи и вопросы » [+] Применение NetworkStream, CryptoStream, StreamWriter/StreamReader