Вопрос № 163941: Здравствуйте, уважаемые эксперты, помогите переписать код шифрования файлов, по методу XOR, в аналогичный но на С#. Код на C++ в приложении....
Вопрос № 163.941
Здравствуйте, уважаемые эксперты, помогите переписать код шифрования файлов, по методу XOR, в аналогичный но на С#. Код на C++ в приложении.
Приложение:
Отправлен: 02.04.2009, 01:54
Вопрос задал: Tomzz (статус: Посетитель)
Всего ответов: 1 Мини-форум вопроса >>> (сообщений: 7)
Отвечает: Micren
Здравствуйте, Tomzz! Вот Ваша программа.
Код:
using System; using System.IO;
namespace _163941 { class Program { /// <summary> /// Длина ключа /// </summary> const int KeyLength = 512; static
void Main(string[] args) { // Проверяем входные параметры if (args.Length != 3) { Console.WriteLine("Запускать программу надо так:"); Console.WriteLine(""Имя программы" "Файл ключа" "Входной файл" "Выходной файл""); return; } // Извлекаем из коммандной строки
string KeyFileName = args[0]; string InFileName = args[1]; string OutFileName = args[2]; // Файловые потоки FileStream KeyFile = null, InFile = null, OutFile = null; try { // Открываем файлы KeyFile = new FileStream(KeyFileName, FileMode.Open, FileAccess.Read, FileShare.Read); InFile = new FileStream(InFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
OutFile = new FileStream(OutFileName, FileMode.Create, FileAccess.Write, FileShare.None); // Ключ будет здесь byte[] Key = new byte[KeyLength]; // Читаем его if (KeyFile.Read(Key, 0, KeyLength) != KeyLength) { Console.WriteLine("Длина ключа должна быть {0} байт", KeyLength); return; }
byte[] Buffer = new byte[KeyLength]; // Буффер long BytesLeft = InFile.Length; // Осталось считать байт // Пока есть что читать while (BytesLeft > 0) { // Читаем int BytesRead = InFile.Read(Buffer, 0, KeyLength); // Кодируем for (int i = 0; i < BytesRead; ++i) {
Buffer[i] ^= Key[i]; } // Пишем OutFile.Write(Buffer, 0, BytesRead); BytesLeft -= BytesRead; } } // Обработчики исключений catch (FileNotFoundException ex) { Console.WriteLine(ex.Message); } catch (Exception ex) { Con
sole.WriteLine(ex.Message); } finally { // Закрываем файлы if (KeyFile != null) KeyFile.Close(); if (InFile != null) InFile.Close(); if (OutFile != null) OutFile.Close(); } } } }
Как вариант могу предложить программу с несколькими потоками. На моей системе выигрыш по времени ~45%.
Код:
using System; using System.Collections.Generic; using System.IO; using System.Threading;
namespace _163941 { class Program { /// <summary> /// Длина ключа /// </summary> const int KeyLength = 512; /
// <summary> /// Файловые потоки /// </summary> static FileStream KeyFile = null, InFile = null, OutFile = null; /// <summary> /// Рабочая очередь /// </summary> static Queue<byte[]> WorkQueue = new Queue<byte[]>(); /// <summary> /// Очередь для выводящего потока /// </summary> static Queue<byte[]> OutQueue = new Queue<byte[]>();
/// <summary> /// Ключ /// </summary> static byte[] Key; static void Main(string[] args) { // Проверяем входные параметры if (args.Length != 3) { Console.WriteLine("Запускать программу надо так:"); Console.WriteLine(""Имя программы" "Файл ключа" "Входной файл" "Вых
одной файл""); return; } // Извлекаем из коммандной строки string KeyFileName = args[0]; string InFileName = args[1]; string OutFileName = args[2]; try { // Открываем файлы KeyFile = new FileStream(KeyFileName, FileMode.Open, FileAccess.Read, FileShare.Read); InFile = new FileStream(InFileName, FileMode.Open, FileAccess.Read,
FileShare.Read); OutFile = new FileStream(OutFileName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true); // Место для ключа Key = new byte[KeyLength]; // Читаем его if (KeyFile.Read(Key, 0, KeyLength) != KeyLength) { Console.WriteLine("Длина ключа должна быть {0} байт", KeyLength); ret
urn; } // Создаем и запускаем потоки Thread[] threads = new Thread[4]; threads[0] = new Thread(InputThread); threads[0].IsBackground = true; threads[1] = new Thread(WorkThread); threads[1].IsBackground = true; threads[2] = new Thread(OutThread); threads[2].IsBackground = true; threads[3] = new Thread(ProgressThread);
threads[3].IsBackground = true; threads[0].Start(); threads[1].Start(); threads[2].Start(); threads[3].Start(); // Ждем завершения threads[0].Join(); threads[1].Join(); threads[2].Join(); threads[3].Join(); } // Обработчики исключений catch (Fil
eNotFoundException ex) { Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { // Закрываем файлы if (KeyFile != null) KeyFile.Close(); if (InFile != null) InFile.Close(); if (OutFile != null) OutFile.Close(); } }
/// <summary> /// Используется для передачи данных потоку вывода прогресса /// </summary> class ProgressEventArgs { public ProgressEventArgs(long bytesTotal) { this.bytesLeave = this.bytesTotal = bytesTotal; } long bytesLeave, bytesTotal; public long BytesTotal { get { return bytesTotal; }
} public long BytesLeave { get { return bytesLeave; } set { bytesLeave = value; progress = (1 - (double)bytesLeave / BytesTotal) * 100; } } double progress; public double Progress { get { return progress; } } } static ProgressEventArgs
progressEvent; static AutoResetEvent ProgressEvent = new AutoResetEvent(false); /// <summary> /// Выводит информацию о прогрессе выполнения /// </summary> static void ProgressThread() { while (!OutThreadDone) { if (ProgressEvent.WaitOne(1000)) { lock(progressEvent) {
Console.Write("{0,5:F2}%", progressEvent.Progress); } } } } static bool InputThreadDone = false; /// <summary> /// Ввод данных из файла /// </summary> static void InputThread() { long bytesLeave = InFile.Length; progressEvent = new ProgressEventArgs(bytesLeave); while (bytesLeave > 0)
{ byte[] buffer = new byte[bytesLeave > KeyLength ? KeyLength : bytesLeave]; long bytesRead = InFile.Read(buffer, 0, buffer.Length); lock (WorkQueue) { WorkQueue.Enqueue(buffer); } bytesLeave -= bytesRead; } InputThreadDone = true; } static bool WorkThreadDone = false;
/// <summary> /// Рабочий поток /// </summary> static void WorkThread() { while (true) { if (WorkQueue.Count > 0) { byte[] workBuffer; lock (WorkQueue) { workBuffer = WorkQueue.Dequeue(); } for (int i = 0; i < workBuffer.Length; ++i)
{ workBuffer[i] ^= Key[i]; } lock (OutQueue) { OutQueue.Enqueue(workBuffer); } } else if (InputThreadDone) break; else Thread.Sleep(50); } WorkThreadDone = true; } static bool OutThreadDone = false; /// <
;summary> /// Вывод данных в файл /// </summary> static void OutThread() { while (true) { if (OutQueue.Count > 0) { byte[] outBuffer; lock (OutQueue) { outBuffer = OutQueue.Dequeue(); } OutFile.Write(outBuffer, 0, outBuffer.Length);
lock(progressEvent) { progressEvent.BytesLeave -= outBuffer.Length; } ProgressEvent.Set(); } else if (WorkThreadDone) break; else Thread.Sleep(50); } OutThreadDone = true; } } }
Кодирование таким методом не далеко не лучшее решение для безопасности данных. В пространстве имен .NET System.Security.Cryptography содержатся классы позволяющие кодировать по алгоритмам соответствующим современным нормам защиты информации(AES,Rijandel,RSA и др.)
Ответ отправил: Micren (статус: Практикант)
Ответ отправлен: 02.04.2009, 03:36
Как сказать этому эксперту "спасибо"?
Отправить SMS
#thank 246631 на номер 1151 (Россия) | Еще номера >>
Вам помогли? Пожалуйста, поблагодарите эксперта за это!
Скажите "спасибо" эксперту, который помог Вам!
Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
на короткий номер 1151 (Россия)
Номер ответа и конкретный текст СМС указан внизу каждого ответа.
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.