2016-10-25 6 views
1

私はエース暗号を使ってファイルを暗号化しています。私は暗号化するためのreadByte関数を使用する場合ワード、パワーポイントファイルを解読する際のエラー

Encrypt(@"E:\test.docx", @"E:\test.enc"); 
Decrypt(@"E:\test.enc", @"E:\test_new.docx"); 

、各バイトを復号化:主な機能には

private static void Encrypt(string inputFilePath, string outputfilePath) 
    { 
     string EncryptionKey = "MAKV2SPBNI99212"; 
     using (Aes encryptor = Aes.Create()) 
     { 
      Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
      encryptor.Key = pdb.GetBytes(32); 
      encryptor.IV = pdb.GetBytes(16); 
      using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create)) 
      { 
       using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) 
       { 
        using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open)) 
        { 
         //int data; 
         //while ((data = fsInput.ReadByte()) != -1) 
         //{ 
         // cs.WriteByte((byte)data); 
         //} 

         byte[] bytes = new byte[fsInput.Length]; 
         while (fsInput.Read(bytes, 0, (int)fsInput.Length) > 0) ; 
         cs.Write(bytes, 0, bytes.Length); 
        } 
       } 
      } 
     } 
    } 

    private static void Decrypt(string inputFilePath, string outputfilePath) 
    { 
     string EncryptionKey = "MAKV2SPBNI99212"; 
     using (Aes encryptor = Aes.Create()) 
     { 
      Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
      encryptor.Key = pdb.GetBytes(32); 
      encryptor.IV = pdb.GetBytes(16); 
      using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open)) 
      { 
       using (CryptoStream cs = new CryptoStream(fsInput, encryptor.CreateDecryptor(), CryptoStreamMode.Read)) 
       { 
        using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create)) 
        { 
         //int data; 
         //while ((data = cs.ReadByte()) != -1) 
         //{ 
         // fsOutput.WriteByte((byte)data); 
         //} 
         byte[] bytes = new byte[fsInput.Length]; 
         while (cs.Read(bytes, 0, (int)fsInput.Length) > 0) ; 
         fsOutput.Write(bytes, 0, bytes.Length); 
        } 
       } 
      } 
     } 
    } 

私は、Wordファイルを復号化、暗号化します。ファイルtest_new.docxが作成され、正常にオープンされます。しかし、私がRead関数を使って多くのバイトを暗号化、解読すると、test_new.docxファイルが作成されますが、エラー内容は開けません。 アイデアはありますか?ありがとう!

答えて

-1

解読されたbytes配列の最後にゼロが多すぎるという問題があります。これは、使用されている暗号では、ブロックされた各ブロックがブロックサイズと一致する必要があり、適合しない場合は、ブロックされます。したがって、実際にはfsInput.Lengthは復号化されたバイトの長さよりも大きくなります。復号化されたバイト数でこれらのゼロを取り除くために

は今、期待通りに動作するはずですあなたのDecrypt方法このコード

using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create)) 
using (BinaryWriter fsDecrypted = new BinaryWriter(fsOutput)) 
using (BinaryReader br = new BinaryReader(cs)) 
    fsDecrypted.Write(br.ReadBytes((int)fsInput.Length)); 

using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create)) 
{ 
    byte[] bytes = new byte[fsInput.Length]; 
    while (cs.Read(bytes, 0, (int)fsInput.Length) > 0) ; 
    fsOutput.Write(bytes, 0, bytes.Length); 
} 

にこのコードを置き換えます。

+1

デフォルトのパディングは、PKCS#7の[PaddingMode.PKCS7]です。パディングなしです。 MSDNの[SymmetricAlgorithm Properties](http://msdn.microsoft.com/en-us/library/System.Security.Cryptography.SymmetricAlgorithm_properties.aspx)ページを参照してください。 @Neil Humbyの答えを見てください。 – zaph

+0

@zaphあなたは絶対に正しいです、私は答えを修正しました。しかし、私は 'BinaryReader'を使って内容を一度に読むことは、Neil Humbyのように' ReadByte() 'を使うよりもパフォーマンスが良いと思います。 – haindl

+0

@zaph解読された 'bytes'の0は、PKCS#7のパディングからではなく、' fsInput.Length'が実際には大きすぎるため、 'byte [] bytes = new byte [fsInput.Length];'私はこの面を反映するために私の答えを修正しました。私の答えに何か誤りがありますか? (私は学ぶつもりです) – haindl

1

解読に間違ったストリーム長を使用していますが、fsInput.Lengthの代わりに実際に読み込んでいるストリームであるcs.Lengthを使用するべきです。 FileStreamとCryptoStreamの長さは同じではないので、それらを交換することはできません。しかし、CryptoStreamも非シークです。つまり、ストリームの終わりを探すことができず、.Lengthを使用するとNotImplementedExceptionがスローされます。したがって、CryptoStreamのような非シーク・ストリームの場合、ストリームが完了するまでReadByte()を使って一度に1バイトを読み込む必要があります。

+0

'新しいBinaryReader(cs).ReadBytes((int)fsInput.Length)'は正しいバイト数を一度に読み込みます。これは、Officeドキュメントの一般的なファイルサイズで一度に1バイトを読み取るよりもパフォーマンスがはるかに優れているはずです。 – haindl

+0

私はcs.Lengthを使用しますが、例外をスローします.cs.Lengthはアクセスできません。 – user2637368

+0

それは本当です。暗号化した後と解読する前のファイルストリームの長さを比較すると、違いがあります。私は大量のファイルを復号化するときに、速度を向上させるために多くのバイトを読み込みたい。このバグは、ecrypt、decypt word、powerpointファイル、その他のファイルが正常に動作している場合にのみ発生します。 – user2637368

0

暗号化ファイルの前に最後にいくつかのバイトを追加しました。バイト配列を解読した後、ファイル長を正確に取得するためにこのバイトを見つける。

+0

私の答えの3つのコード行だけを使用する場合は、これらの余分なバイトを絶対に追加する必要はありません。私は自分のコードをテストしたが、他の修正を加えなくても動作する。 (私はなぜそれが一度落とされたのかわかりません。) – haindl

関連する問題