Доступ к расшифрованному зашифрованному файлу Rijndael с помощью StreamReader без записи на диск

В настоящее время я работаю над шифрованием/дешифрованием простых текстовых файлов, встроенных в файл .dll. Файлы с простым текстом представляют собой сценарии и анализируются по мере необходимости.

На данный момент вот как загружаются (обычные текстовые) файлы сценариев:

string RunLocation = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Assembly _assembly = Assembly.LoadFrom(RunLocation + "\\<name of dll>.dll");
s = new StreamReader(_assembly.GetManifestResourceStream(File));
RunScript(s);

Метод RunScript считывает одну строку скрипта в строку, а затем анализирует ее. Он просматривает каждую строку по очереди и выполняет каждое из действий, которые мы определяем в сценарии, по мере их обнаружения.

Так как наши dll-файлы в любом случае не зашифрованы, мы решили, что должны шифровать каждый из файлов скриптов, прежде чем они будут встроены в dll. Мы остановились на алгоритме Rijndael из-за простоты его реализации на C#/.NET.

В настоящее время шифрование работает следующим образом:

FileStream fileStreamForEncryption = new FileStream (inputFileToBeEncrypted, FileMode.Create);
RijndaelManaged rijndaelCryptography = new RijndaelManaged();
CryptoStream encryptionStream = new CryptoStream(fileStreamForEncryption, rijndaelCryptography .CreateEncryptor(key, iv), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
  cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fileStreamForEncryption .Close()

Это означает, что расшифровка — это вопрос запуска нескольких команд и получения расшифрованного файла... за исключением того, что из-за дизайна остального кода (шифрование, похоже, было "как только мы запустим систему для заданный стандарт"), файл должен быть возвращен как объект StreamReader. На данный момент я расшифровываю запрошенный файл следующим образом:

string decodedFile = null;
FileStream fileToDecrypt= new FileStream(_assembly.GetManifestResourceStream(File).ToString(), FileMode.Open);
/* I know that the above line is overly complicated, it's because our files are read into StreamReader objects (as I've explained above) */
RijndaelManaged rijndaelCryptography = new RijndaelManaged();
try
{
  CryptoStream cs = new CryptoStream(fileToDecrypt, rijndaelCryptography .CreateDecryptor(key, iv), CryptoStreamMode.Read);
  using (StreamReader decryptReader = new StreamReader(cs))
  {
    decodedFile = decryptReader.ReadToEnd();
  }
catch (Exception e)
{
MessageBox.Show(e.Message);
}

Кто-нибудь знает, как я могу расшифровать файл с помощью Rijndael, но сделать вывод доступным как / для чтения в экземпляр объекта StreamReader?

Я долго искал в Интернете способы сделать это, и самое близкое, что я нашел, это копирование содержимого decryptReader в другой объект StreamReader вместо расшифровки в строку, но кажется, что вы не можете скопировать содержимое один StreamReader на другой StreamReader - поправьте меня, если я ошибаюсь.

Я бы хотел изменить как можно меньше существующей (которой я не поделился здесь) кодовой базы, поскольку это может привести к возникновению ошибок. Я также хотел бы сделать это, не записывая файл обратно на диск (очевидно, есть причина, по которой мы их шифруем).

Заранее спасибо, и извините, если я выразился недостаточно ясно или немного расплывчато. Я могу добавить больше информации, если вам это нужно, чтобы помочь мне.

Джейми


person Jamie Taylor    schedule 11.01.2012    source источник
comment
Оберните все свои объекты IDisposable (FileStream, RijndaelManaged, CryptoStream и StreamReader) в блоки using и исключите вызовы Close().   -  person Jesse C. Slicer    schedule 11.01.2012
comment
К вашему сведению, чтобы расшифровать данные, вы должны хранить ключ, который можно легко захватить. Кроме того, чтобы использовать скрипт, он должен быть расшифрован, что также может быть легко перехвачено. Если ваше приложение запущено на чужом компьютере, вы больше не имеете контроля над своим приложением. Что-то такое простое, как Process Explorer, может обойти ваш drm.   -  person Bengie    schedule 11.01.2012
comment
@ Бенги Да, я знаю. Мы считаем, что любой, кто действительно, отчаянно хочет знать, что находится в файлах сценариев, вероятно, имеет слишком много свободного времени. Учитывая, что руководство пользователя, которое будет выпущено вместе с программным обеспечением, будет иметь раздел создания сценариев (конечные пользователи смогут загружать свои собственные незашифрованные сценарии).   -  person Jamie Taylor    schedule 11.01.2012
comment
@ JesseC.Slicer Спасибо, что напомнили мне. Я собирался вернуться к каждому из IDisposables в использовании блоков, как только я заставлю код работать правильно.   -  person Jamie Taylor    schedule 11.01.2012


Ответы (2)


Вы можете просто преобразовать содержимое декодированного файла в массив байтов и представить его как поток:

var stream = new System.IO.MemoryStream(System.Text.Encoding.Unicode.GetBytes(decodedFile));
var streamReader = new StreamReader(stream);

Кроме того, вам, вероятно, следует избавиться от экземпляра RijndaelManaged, поместив его в блок using:

using (RijndaelManaged rijndaelCryptography = new RijndaelManaged())
{
    ...
}

Обновить

Вы можете получить зашифрованный файл вот так, и конструктор CryptoStream все равно будет счастлив:

Stream fileToDecrypt= _assembly.GetManifestResourceStream(File);
...
CryptoStream cs = new CryptoStream(fileToDecrypt, rijndaelCryptography.CreateDecryptor(key, iv), CryptoStreamMode.Read);
person Rich O'Kelly    schedule 11.01.2012
comment
Теперь, когда у нас есть расшифрованный сценарий, прочитанный в StreamReader, я заметил, что при чтении файла сценария произошла ошибка. Нам удалось выяснить, что использование FileStream приводит к тому, что код явно ищет файл в том же каталоге, что и dll, а не встроенный в dll. Проблема в том, что CryptoStream требовал FileStream для шифрования данных. Вы знаете способ обойти это? - person Jamie Taylor; 11.01.2012
comment
@JamieTaylor Для конструктора CryptoStream требуется только экземпляр Stream — вы можете использовать Assembly.GetManifestResourceStream(resourceName), чтобы получить встроенный ресурс (ваш файл) - person Rich O'Kelly; 11.01.2012
comment
Другой парень, работавший над этим кодом, сказал: «Что? Чувак! Это его благодарность, и что вы были очень полезны. Спасибо, сэр. - person Jamie Taylor; 11.01.2012

Я долго искал в Интернете способы сделать это, и самое близкое, что я нашел, это копирование содержимого decryptReader в другой объект StreamReader вместо расшифровки в строку, но кажется, что вы не можете скопировать содержимое один StreamReader на другой StreamReader - поправьте меня, если я ошибаюсь.

Вы лишь немного правы. Хотя вы не можете копировать из одного StreamReader в другой, вы можете читать из одного StreamReader и записывать в StreamWriter, поддерживаемый, скажем, MemoryStream. Затем вы можете обернуть StreamReader вокруг данных в MemoryStream, которые были записаны StreamWriter.

Так что то, что вы хотите сделать, вполне возможно. Фактически, самая большая проблема, которую я вижу для вашей установки, связана с ключом дешифрования.

person Randolpho    schedule 11.01.2012