7

私は、理想的にはRijndaelを使用して、nの長さのファイルを安全に暗号化/復号化する必要がある状況にありますが、間違いなく256ビット暗号化です。

私は以前に暗号化をいじってみましたが、文字列とバイト配列を暗号化/復号化して非常に満足しています。ただし、ファイルのサイズがわからないため(そして、問題のファイルが非常に大きくなる可能性が非常に高い(〜2.5gb))、それらをバイト配列にロードして、暗号化/復号化することはできません。以前と同じようにシングルバウンド。

そこで、Googleで少し読んだ後、答えはファイルをチャンクで暗号化および復号化することであることがわかったので、次のコードを作成しました。

private static void Enc(string decryptedFileName, string encryptedFileName)
{            
   FileStream fsOutput = File.OpenWrite(encryptedFileName);
   FileStream fsInput = File.OpenRead(decryptedFileName);

   byte[] IVBytes = Encoding.ASCII.GetBytes("1234567890123456");

   fsOutput.Write(BitConverter.GetBytes(fsInput.Length), 0, 8);
   fsOutput.Write(IVBytes, 0, 16);

   RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC};
   ICryptoTransform encryptor = symmetricKey.CreateEncryptor(passwordDB.GetBytes(256 / 8), IVBytes);
   CryptoStream cryptoStream = new CryptoStream(fsOutput, encryptor, CryptoStreamMode.Write);

   for (long i = 0; i < fsInput.Length; i += chunkSize)
   {
      byte[] chunkData = new byte[chunkSize];
      fsInput.Read(chunkData, 0, chunkSize);
      cryptoStream.Write(chunkData, 0, chunkData.Length);
   }
   cryptoStream.Close();
   fsInput.Close();
   fsInput.Dispose();
   cryptoStream.Dispose();
}

private static void Dec(string encryptedFileName, string decryptedFileName)
{
    FileStream fsInput = File.OpenRead(encryptedFileName);
    FileStream fsOutput = File.OpenWrite(decryptedFileName);

    byte[] buffer = new byte[8];
    fsInput.Read(buffer, 0, 8);

    long fileLength = BitConverter.ToInt64(buffer, 0);

    byte[] IVBytes = new byte[16];
    fsInput.Read(IVBytes, 0, 16);

    RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };
    ICryptoTransform decryptor = symmetricKey.CreateDecryptor(passwordDB.GetBytes(256 / 8), IVBytes);
    CryptoStream cryptoStream = new CryptoStream(fsOutput,decryptor,CryptoStreamMode.Write);

    for (long i = 0; i < fsInput.Length; i += chunkSize)
    {
        byte[] chunkData = new byte[chunkSize];
        fsInput.Read(chunkData, 0, chunkSize);
        cryptoStream.Write(chunkData, 0, chunkData.Length);
    }
    cryptoStream.Close();
    cryptoStream.Dispose();
    fsInput.Close();
    fsInput.Dispose();                      
} 

それはすべて私には「よく見える」が、悲しいことに、見た目はだまされているように見える!

暗号化はエラーなしで機能しますが、復号化中に「cryptoStream.Close()」メソッドは次の例外をスローします。

System.Security.Cryptography.CryptographicExceptionは未処理でしたMessage="パディングは無効であり、削除できません。"
Source = "mscorlib" StackTrace:at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte [] inputBuffer、Int32 inputOffset、Int32 inputCount、Byte []&outputBuffer、Int32 outputOffset、PaddingMode paddingMode、Boolean fLast)at System.Security.Cryptography .RijndaelManagedTransform.TransformFinalBlock(Byte [] inputBuffer、Int32 inputOffset、Int32 inputCount)at System.Security.Cryptography.CryptoStream.FlushFinalBlock()at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposed)at System.IO.Stream.Close ()

また、暗号化されていないファイルサイズが予想されるファイルサイズと一致していないようです(約8バイトから約60バイトの範囲)

以下のように、RijndaelManagedオブジェクトの作成行を変更して、パディングタイプを含めることにより、例外を「修正」しました。

RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC,Padding=PaddingMode.None };

しかし、ファイルサイズはまだ一致しておらず、予想通り、暗号化されていないばかりのファイルはバロニーです!

私は今、暗号化/復号化で自分の快適ゾーンの外にいることを認めます、そしてそれはおそらく新人の間違いです-しかし私はそれを見つけることができません!

これを解決するための助けをいただければ幸いです。

4

3 に答える 3

5

問題は、私が使用していたことです:

passwordDB.GetBytes(256 / 8)

EncryptionメソッドとDecryptionメソッドの両方でRijndaelManagedオブジェクトのコンストラクター内にあり、復号化を試みる前にpasswordDBオブジェクトを再初期化していませんでした。

解決策は、次のように、EncメソッドとDecメソッドの両方の最初の行にpasswordDBオブジェクトの構築を含めることでした。

        private static void Enc(string decryptedFileName, string encryptedFileName)
        {
            PasswordDeriveBytes passwordDB = new PasswordDeriveBytes("ThisIsMyPassword", Encoding.ASCII.GetBytes("thisIsMysalt!"), "MD5", 2);
            byte[] passwordBytes = passwordDB.GetBytes(128 / 8);

            using (FileStream fsOutput = File.OpenWrite(encryptedFileName))
            {
                using(FileStream fsInput = File.OpenRead(decryptedFileName))
                {
                    byte[] IVBytes = Encoding.ASCII.GetBytes("1234567890123456");

                    fsOutput.Write(BitConverter.GetBytes(fsInput.Length), 0, 8);
                    fsOutput.Write(IVBytes, 0, 16);

                    RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC,Padding=PaddingMode.ANSIX923};
                    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(passwordBytes, IVBytes);                   

                    using (CryptoStream cryptoStream = new CryptoStream(fsOutput, encryptor, CryptoStreamMode.Write))
                    {
                        for (long i = 0; i < fsInput.Length; i += chunkSize)
                        {
                            byte[] chunkData = new byte[chunkSize];
                            int bytesRead = 0;
                            while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
                            {
                                if (bytesRead != 16)
                                {
                                    for (int x = bytesRead - 1; x < chunkSize; x++)
                                    {
                                        chunkData[x] = 0;
                                    }
                                }
                                cryptoStream.Write(chunkData, 0, chunkSize);
                            }
                        }
                        cryptoStream.FlushFinalBlock();
                    }
                }
            }            
        }

        private static void Dec(string encryptedFileName, string decryptedFileName)
        {
            PasswordDeriveBytes passwordDB = new PasswordDeriveBytes("ThisIsMyPassword", Encoding.ASCII.GetBytes("thisIsMysalt!"), "MD5", 2);
            byte[] passwordBytes = passwordDB.GetBytes(128 / 8);

            using (FileStream fsInput = File.OpenRead(encryptedFileName))
            {
                using (FileStream fsOutput = File.OpenWrite(decryptedFileName))
                {
                    byte[] buffer = new byte[8];
                    fsInput.Read(buffer, 0, 8);

                    long fileLength = BitConverter.ToInt64(buffer, 0);

                    byte[] IVBytes = new byte[16];
                    fsInput.Read(IVBytes, 0, 16);


                    RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC,Padding=PaddingMode.ANSIX923};
                    ICryptoTransform decryptor = symmetricKey.CreateDecryptor(passwordBytes, IVBytes);

                    using (CryptoStream cryptoStream = new CryptoStream(fsOutput, decryptor, CryptoStreamMode.Write))
                    {
                        for (long i = 0; i < fsInput.Length; i += chunkSize)
                        {
                            byte[] chunkData = new byte[chunkSize];
                            int bytesRead = 0;
                            while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
                            {
                                cryptoStream.Write(chunkData, 0, bytesRead);
                            }
                        }
                    }
                }
            }
        }

それは男子生徒のエラーでなければならないことを知っていました:P

于 2010-07-28T10:54:30.120 に答える
3

Stream.Readメソッドは、ストリームから実際に読み取られているバイト数を返します。

この戻り値は、次の行のWriteメソッドの最後のパラメーターとして使用する必要があります。

私のコードは次のようになります。

byte[] chunkData = new byte[chunkSize];   
var bytesRead = 0;
while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
{
    cryptoStream.Write(chunkData, 0, bytesRead);
}
于 2010-07-28T08:59:37.110 に答える
0

ストリームを暗号化/復号化するためのCryptoStreamクラスがあります

于 2016-08-09T12:40:29.033 に答える