Зашифруйте файл, используя File.Encrypt, а затем расшифруйте его в потоке памяти.

Мне нужно реализовать простое шифрование файлов, а затем расшифровать его, когда это необходимо, в поток памяти. Кажется, что самый простой способ сделать это с File.Encrypt, но возможно ли расшифровать файл в потоке памяти, вместо того, чтобы дешифровать файл перед чтением его в поток памяти и, таким образом, выставить его на некоторое время?

И если File.Encrypt не лучший способ для этого сценария, что бы вы порекомендовали?

3 ответа

File.Encrypt это функция ОС, но, похоже, вы действительно хотите контролировать, как выполняется шифрование.

http://msdn.microsoft.com/en-us/library/system.io.file.encrypt.aspx

// This is where the data will be written do.
MemoryStream dataStream = new MemoryStream();

// The encryption vectors
byte[] key = {145,12,32,245,98,132,98,214,6,77,131,44,221,3,9,50};
byte[] iv  = {15,122,132,5,93,198,44,31,9,39,241,49,250,188,80,7};

// Build the encryption mathematician
using (TripleDESCryptoServiceProvider encryption = new TripleDESCryptoServiceProvider())
using (ICryptoTransform transform = encryption.CreateEncryptor(key, iv))
using (Stream encryptedOutputStream = new CryptoStream(dataStream, transform, CryptoStreamMode.Write))
using (StreamWriter writer = new StreamWriter(encryptedOutputStream))
{
    // In this block, you do your writing, and it will automatically be encrypted
    writer.Write("This is the encrypted output data I want to write");
}

Шифрование не для слабонервных. Тем не менее, имейте в виду, что вы действительно должны иметь четкое представление о регулярном вводе-выводе и потоках данных, прежде чем пытаться сделать это.

Это был первый код шифрования, который я написал - будьте осторожны, хотя хорошая отправная точка для понимания происходящего, статические пароли и статические соли - плохая идея! (спасибо за выделение этого CodesInChaos)

Вы можете расшифровать любой поток, который вам нравится, включая прямой поток памяти...

FileInfo file = new FileInfo("SomeFile");
using (FileStream inFs = file.OpenRead())
{
    using (MemoryStream outMs = new MemoryStream())
    {
        encryption.Decrypt(inFs, outMs);                    

        BinaryFormatter bf = new BinaryFormatter();
        targetType target= bf.Deserialize(outMs) as targetType;
    }
}

где шифрование является одним из них:

public class EncryptionHelper
{        
    static SymmetricAlgorithm encryption; 
    static string password = "password";
    static string salt = "this is my salt. There are many like it, but this one is mine.";

    static EncryptionHelper()
    {
        encryption = new RijndaelManaged();
        Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));

        encryption.Key = key.GetBytes(encryption.KeySize / 8);
        encryption.IV = key.GetBytes(encryption.BlockSize / 8);
        encryption.Padding = PaddingMode.PKCS7;
    }

    public void Encrypt(Stream inStream, Stream OutStream)
    {
        ICryptoTransform encryptor = encryption.CreateEncryptor();
        inStream.Position = 0;
        CryptoStream encryptStream = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
        inStream.CopyTo(encryptStream);
        encryptStream.FlushFinalBlock();

    }


    public void Decrypt(Stream inStream, Stream OutStream)
    {
        ICryptoTransform encryptor = encryption.CreateDecryptor();
        inStream.Position = 0;
        CryptoStream encryptStream = new CryptoStream(inStream, encryptor, CryptoStreamMode.Read);
        encryptStream.CopyTo(OutStream);
        OutStream.Position = 0;  
    }
}

Внедрение Crypto обманчиво просто и на самом деле довольно утомительно, в нем много деталей, а неправильные - это обычно то, что эксплуатируется с точки зрения безопасности. Лучше всего использовать высокоуровневую инфраструктуру шифрования, которая скрывает эти детали: ivs, salt, mac, сравнения, заполнение, поворот ключа, и хотя для высокоуровневых сред не исключено, что детали неверны, когда они это делают, они обнаруживаются и исправлено, фрагменты кода при переполнении стека обычно этого не делают.

Я портировал фреймворк Google Keyczar, чтобы такая библиотека высокого уровня существовала для C#.

Keyczar-DotNet

И это можно использовать для шифрования и дешифрования потоков IO.

Установите в свой проект с помощью Nuget

PM> Install-Package Keyczar -Pre

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

PM> KeyczarTool.exe create --location=path_to_key_set --purpose=crypt
PM> KeyczarTool.exe addkey --location=path_to_key_set --status=primary

Затем в своем коде вы можете использовать любой поток ввода-вывода, который вы хотите для обоих шифрований:

using(var encrypter = new Encrypter("path_to_key_set"))
{
     encrypter.Encrypt(plaintextStream, ciphertextStream);
}

и расшифровка:

using(var crypter = new Crypter("path_to_key_set"))
{
     crypter.Decrypt(ciphertextStream, plaintextStream);
}
Другие вопросы по тегам