Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Криптография (DES)


Автор: mr.Anderson 27.6.2010, 21:40
Нужно зашифровать файл по алгоритму DES (желательно, он вроде проще всех в написании обертки в дотнете, хотя, в общем, все равно, какой использовать). Естественно, потом нужно его будет расшифровывать.
Я навалял вот такой код (код шифрования содран из MSDN, остальные навески мои, но их тут немного):
Код

public DesCrypto()
        {
            _des = new DESCryptoServiceProvider();
        }

        private void _DesCrypt(string inName, string outName, ICryptoTransform cryptoTransform)
        {
            // создаем входные и выходные файловые потоки
            FileStream fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
            FileStream fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write);
            fout.SetLength(0);
            // создадим переменные, которые помогут читать и записывать информацию
            byte[] bin = new byte[100]; // это промежуточное хранилище для шифрования
            long rdlen = 0; // общее количество обработанных байтов
            long totlen = fin.Length; // полное количество байтов в исходном файле
            // шифруем файл            
            CryptoStream encStream = new CryptoStream(fout, cryptoTransform, CryptoStreamMode.Write);
            // читаем байты блоками из входного файла, шифруем и записываем в выходной
            while (rdlen < totlen)
            {
                int len = fin.Read(bin, 0, 100);
                encStream.Write(bin, 0, len);
                rdlen = rdlen + len;
                ProgressChanged(rdlen);                
            }
            encStream.Close();
            fout.Close();
            fin.Close();
        }
        
        public void EncryptData(string inName, string outName, byte[] desKey)
        {            
            _DesCrypt(inName, outName, _des.CreateEncryptor(desKey, desKey));
        }

Вроде бы ничего хитрого, однако летит исключение на _des.CreateEncryptor(...) (в функции EncryptData). Ключ, как я прочитал в вики, должен быть длиной 56 битов. Ну я попробовал сформировать его так:
Код

byte[] key = new byte[56];
for (int i = 0; i < 56; i++)
    key[i] = (byte) new Random((int) DateTime.Now.Ticks).Next(0, 2);

Конечно, может, это тупизм, и можно намного проще. Но я не нашел примеров, как именно. Подскажите, как правильно сформировать ключ. Плюс, нормаьлная ли это практика, юзать при создании енкриптора/декриптора одинаковые ключ и вектор инициализации? Про вектор тоже толком нигде не написано, как его правильно формировать.

Автор: mr.Anderson 30.6.2010, 01:14
Нарооод, неужели никто не знает? Если совсем никаких подвижек в этой стороне нет, то дайте хотя бы работающий пример (или линк на него) шифрования и расшифровки текстового файла через другой алгоритм шифрования, TripleDES, например, или ему подобные. Топтаться на месте тоже не совсем хорошо, а ответа на свой вопрос в гугле я найти не смог.

Автор: Lunatic2009 30.6.2010, 06:07
Попробуйте так, это немного переделанный пример из msdn:

Код

    public class Program
    {
        public static void Main(string[] args)
        {
            byte[] desKey = new byte[] { 1, 2, 4, 5, 6, 7, 8, 9 };
            byte[] desIV = new byte[] { 1, 2, 4, 5, 6, 7, 8, 9 };

            EncryptDecryptData("C:\\1.txt", "C:\\1_enc.txt", desKey, desIV, true);
            EncryptDecryptData("C:\\1_enc.txt", "C:\\2.txt", desKey, desIV, false);
        }

        private static void EncryptDecryptData(string inputFilePath, string outputFilePath, byte[] desKey, byte[] desIV, bool isEncrypt)
        {
            FileStream inputStream = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read);
            FileStream outputStream = new FileStream(outputFilePath, FileMode.OpenOrCreate, FileAccess.Write);

            DES des = new DESCryptoServiceProvider();
            CryptoStream cryptoStream;

            if (isEncrypt)
            {
                cryptoStream = new CryptoStream(outputStream, des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write);
            }
            else
            {
                cryptoStream = new CryptoStream(outputStream, des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Write);
            }

            byte[] data = new byte[100];
            int dataLength = 0;

            while (inputStream.Position < inputStream.Length)
            {
                dataLength = inputStream.Read(data, 0, data.Length);
                cryptoStream.Write(data, 0, dataLength);
            }

            cryptoStream.Close();

            inputStream.Close();
            outputStream.Close();
        }
    }


Насчет длины ключа(из msdn):
Этот алгоритм поддерживает ключи длиной 64 бита.

Насчет ключа и вектора(из msdn):
Предположим, что Алиса и Боб являются двумя сторонами, которые хотят осуществлять связь по незащищенному каналу; они могли бы воспользоваться шифрованием с закрытым ключом следующим образом. Алиса и Боб соглашаются использовать некоторый определенный алгоритм (например, AES) с определенным ключом и вектором инициализации.Алиса пишет сообщение и создает сетевой поток, через который можно отправить это сообщение (например, именованный канал или канал электронной почты).Затем она шифрует текст с помощью ключа и вектора инициализации и по интрасети пересылает зашифрованное сообщение и вектор инициализации Бобу.Боб принимает зашифрованный текст и осуществляет расшифровку, используя ранее согласованные ключ и вектор инициализации.Если происходит перехват передаваемых данных, злоумышленник не может восстановить исходное сообщение, так как ему не известны ключ и вектор инициализации.В этой ситуации в секрете должен сохраняться только ключ.В более реалистичном случае либо Алиса, либо Боб создает закрытый ключ и использует шифрование с открытым ключом (асимметричное) для передачи другой стороне закрытого (симметричного) ключа.

Автор: mr.Anderson 30.6.2010, 21:04
Сами-то проверяли? Не работает, разумеется. Переделывать тут ничего не надо, про работу самого алгоритма я пока ничего не говорил, исключение летит при попытке CreateEncryptor с сообщением "Размер ключа недопустим для данного алгоритма". В вашем примере создания ключа проблема осталась точно такой же.

Автор: Lunatic2009 30.6.2010, 21:25
Естественно проверял, пример рабочий... или по вашему
Код

byte[] desKey = new byte[] { 1, 2, 4, 5, 6, 7, 8, 9 };

не 64 бита?

Автор: mr.Anderson 3.7.2010, 15:03
Все получилось. Ваш пример действительно заработал, однако мой заработал тоже. Проблема была в том, что я не углядел, что в вашем коде в объявлении переменной-ключа была пропущена тройка (я перечислил от 1 до 9 все цифры).

+1 за помощь, сам бы не разобрался.

Автор: Lunatic2009 3.7.2010, 20:23
Прошу прощения, что не усмотрел, ошибаются все, но, все хорошо, что хорошо кончается... smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)