6

単純なファイル暗号化を実装し、必要に応じてメモリ ストリームに復号化する必要があります。最も簡単な方法は File.Encrypt でこれを行うようですが、ファイルをメモリ ストリームに読み取る前に復号化してしばらく公開するのではなく、ファイルをメモリ ストリームに復号化することは可能ですか?

File.Encrypt がこのシナリオに最適な方法ではない場合、どの方法をお勧めしますか?

4

3 に答える 3

2

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 とデータ ストリームについて十分に理解しておく必要があります。

于 2013-02-08T17:19:00.840 に答える
1

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

次に、コードで、両方の暗号化に必要な 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);
}
于 2013-02-08T19:39:53.157 に答える
1

これは私が書いた最初の暗号化コードでした - 何が起こっているのかを理解するための良い出発点ですが、静的なパスワードと静的なソルトは悪い考えです! (この 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;  
    }
}
于 2013-02-08T17:12:19.877 に答える