単純なファイル暗号化を実装し、必要に応じてメモリ ストリームに復号化する必要があります。最も簡単な方法は File.Encrypt でこれを行うようですが、ファイルをメモリ ストリームに読み取る前に復号化してしばらく公開するのではなく、ファイルをメモリ ストリームに復号化することは可能ですか?
File.Encrypt がこのシナリオに最適な方法ではない場合、どの方法をお勧めしますか?
単純なファイル暗号化を実装し、必要に応じてメモリ ストリームに復号化する必要があります。最も簡単な方法は File.Encrypt でこれを行うようですが、ファイルをメモリ ストリームに読み取る前に復号化してしばらく公開するのではなく、ファイルをメモリ ストリームに復号化することは可能ですか?
File.Encrypt がこのシナリオに最適な方法ではない場合、どの方法をお勧めしますか?
File.Encrypt
は OS の機能ですが、暗号化の実行方法を制御したいようです。
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");
}
暗号化は気弱な人向けではありません。ただし、これを試みる前に、通常の IO とデータ ストリームについて十分に理解しておく必要があります。
Crypto の実装は一見簡単ですが、実際にはかなり面倒です。多くの詳細があり、詳細が間違っていると、通常、セキュリティに関して悪用されます。ベスト プラクティスは、ivs、salt、mac、比較、パディング、キー ローテーションなどの詳細を隠す高レベルの暗号化フレームワークを使用することです。高レベルのフレームワークで詳細が間違っている可能性は低いとは言えませんが、間違っている場合は発見されます。スタックオーバーフローのコードスニペットは一般的にそうではありません。
私はGoogle Keyczarフレームワークを移植しているので、そのような高レベルのライブラリが C# 用に存在します。
また、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
次に、コードで、両方の暗号化に必要な IO ストリームを使用できます。
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);
}
これは私が書いた最初の暗号化コードでした - 何が起こっているのかを理解するための良い出発点ですが、静的なパスワードと静的なソルトは悪い考えです! (この 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;
}
}