1

私は C# と暗号化にまったく慣れていないので、しばらくお待ちください。いくつかのバイナリ データ (「オブジェクト」 - 実際にはほとんどがオブジェクトの一部のみであるため、シリアライゼーション、BinaryWriter などを使用できない/使用しない) を保存し、それをメモリに暗号化してから FileStream を使用して書き込みたい. 最初はある種の Xor を使用したいと思っていましたが、簡単に破ることができるとは知らなかったので、コードを変更して Aes を使用するようにしました。

問題は、比較的大きなファイルがいくつかあり、多くの場合、32 バイトのデータを変更または読み取るだけでよいということです。したがって、データの 1 つのチャンクのみを暗号化でき、必要なデータのチャンクのみを復号化できなければなりません。今のところ、次の解決策しか思いつきませんでした。

データを保存するときは、すべてのデータをループし、ループ内でデータのチャンクを暗号化してファイルに書き込みます。読み取り中に、データのチャンクを読み取るループがあり、ループ内で復号化を宣言する必要がありますが、これは非常に非効率的です。

暗号化と保存のコードは次のとおりです。

        //setup file stream for saving data
        FileStream fStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, 1024, false);

        //setup encryption (AES)
        SymmetricAlgorithm aes = Aes.Create();
        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 };
        aes.Padding = PaddingMode.None;
        ICryptoTransform encryptor = aes.CreateEncryptor(key, iv);

        foreach(....)
        {
           //data manipulation

           //encryption
           MemoryStream m = new MemoryStream();
           using (Stream c = new CryptoStream(m, encryptor, CryptoStreamMode.Write))
              c.Write(data, 0, data.Length);
           byte[] original = new byte[32];
           original = m.ToArray();
           fStream.Write(original, 0, original.Length);
        }

キーと iv は、デバッグと問題解決を容易にするためにハードコーディングされています。これが機能するようになったら、キーと iv の生成方法を変更します。

読み取りと復号化のコードは次のとおりです。 FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false);

            //setup encryption (AES)
            SymmetricAlgorithm aes = Aes.Create();
            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 };
            aes.Padding = PaddingMode.None;

            //reading
            while (numBytesToRead > 0)
            {
                byte[] original = new byte[32];
                byte[] data = new byte[32];
                int len = fStream.Read(original, 0, 32);

                //error checking ...

               //decryption
                ICryptoTransform decryptor = aes.CreateDecryptor(key, iv);  //this is a slow operation
                MemoryStream m = new MemoryStream();
                using (Stream c = new CryptoStream(m, decryptor, CryptoStreamMode.Write))
                    c.Write(original, 0, original.Length);
                data = m.ToArray();

                //data manipulation ...
            }

問題は、ループ内でデクリプタを作成するのは非常に非効率的であるということです。かなりのデータ量になります。ループに入る前に作成すると、適切に復号化できず、暗号化を変更する必要があります (ループの前に暗号化ストリームとメモリ ストリームを宣言します) が、必要なデータのチャンクのみを暗号化/復号化することはできません。また、ランダムな読み取り/書き込みのみを必要とするファイルは多くありません。たとえば、一部のファイルでは、特定の位置からファイルの最後まで読み取りたい場合がありますが、これは非常に多くなる可能性があります。

これについてどう思いますか。これを達成するためのより良い方法はありますか?暗号化アルゴリズムが異なる可能性があります(最初はある種のxorを使用したかったのですが、「クラック」するのは非常に簡単であることがわかりました)?

psメモリ内で暗号化したいので、シーク可能なストリームを使用する必要があります。

4

4 に答える 4

1

ECB 暗号化モード ( CipherMode.ECB) を使用できます。他の暗号化モードでは、暗号化および/またはプレーン テキストが次のテキスト ブロックにフィードバックされ、暗号化/復号化されます。これにより、繰り返される部分が別の方法で暗号化されるため、セキュリティが強化されます。ただし、完全なストリームを復号化する必要があります。

電子コード ブック (ECB) モードでは、各ブロックが個別に暗号化されるため、暗号ブロック境界でのランダム アクセスを実装できます。ただし、ECB は、特にプレーン テキストが反復的な場合に脆弱性をもたらします。 こちらをご覧ください

于 2011-02-23T11:59:32.003 に答える
1

完全なランダムアクセスが必要な場合は、ECB が適しています (以前の回答で推奨されているように)。ブロックごとに暗号化ストリームを再作成する必要はありません。これは、IV を使用せず、ブロックを暗号化してもストリームが並べ替えられないためです (暗号文が前のブロックまたはブロックの位置に依存する他のほとんどのモードとは異なります)。ストリーム)。ウィキペディアには、このモードの問題の 1 つを示す素敵な図(ciphertux の図) があります。

ファイルがより大きなチャンク (仮想ディスク内のデータベース レコードやディスク セクターなど) で論理的に構成されている場合は、それらをユニットとして暗号化することを検討する必要があります。CBC モードでは、各チャンクを書き込むたびに新しいランダム IV を生成し、ブロックと共に保存します (したがって、チャンクごとにさらに 32 バイトのストレージを使用します)。 1 バイトは変更されますが、セキュリティははるかに優れています。

于 2011-02-23T16:17:51.180 に答える
0

ECB の代わりに GCM を使用することについてのヒントがありました。ECB は、おそらくあまり安全な方法ではないことをご存知でしょう。私は現在、Bouncy Castle API を使用してプロトタイプを実装しています (このスレッドを確認してください: https://stackoverflow.com/a/10366194/637783 )。

于 2012-09-07T08:27:58.313 に答える