7

我在使用下面的代码时遇到了一些问题。我在需要加密的临时位置有一个文件,此函数会加密该数据,然后将其存储在“pathToSave”位置。

检查时似乎没有正确处理整个文件 - 我的输出中缺少一些位,我怀疑这与 while 循环没有在整个流中运行有关。

顺便说一句,如果我尝试在 while 循环之后调用 CryptStrm.Close() ,我会收到一个异常。这意味着如果我尝试解密文件,我会收到文件已在使用错误!

尝试了所有通常的方法,我在这里查看了类似的问题,任何帮助都会很棒。

谢谢

public void EncryptFile(String tempPath, String pathToSave)
    {
        try
        {
            FileStream InputFile = new FileStream(tempPath, FileMode.Open, FileAccess.Read);
            FileStream OutputFile = new FileStream(pathToSave, FileMode.Create, FileAccess.Write);

            RijndaelManaged RijCrypto = new RijndaelManaged();

            //Key
            byte[] Key = new byte[32] { ... };

            //Initialisation Vector
            byte[] IV = new byte[32] { ... };

            RijCrypto.Padding = PaddingMode.None;
            RijCrypto.KeySize = 256;
            RijCrypto.BlockSize = 256;
            RijCrypto.Key = Key;
            RijCrypto.IV = IV;

            ICryptoTransform Encryptor = RijCrypto.CreateEncryptor(Key, IV);

            CryptoStream CryptStrm = new CryptoStream(OutputFile, Encryptor, CryptoStreamMode.Write);

            int data;
            while (-1 != (data = InputFile.ReadByte()))
            {
                CryptStrm.WriteByte((byte)data);
            }
        }
        catch (Exception EncEx)
        {
            throw new Exception("Encoding Error: " + EncEx.Message);
        }
    }

编辑:

我假设我的问题与加密有关。我的解密可能是罪魁祸首

        public String DecryptFile(String encryptedFilePath)
    {
        FileStream InputFile = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read);

        RijndaelManaged RijCrypto = new RijndaelManaged();

        //Key
        byte[] Key = new byte[32] { ... };

        //Initialisation Vector
        byte[] IV = new byte[32] { ... };

        RijCrypto.Padding = PaddingMode.None;
        RijCrypto.KeySize = 256;
        RijCrypto.BlockSize = 256;
        RijCrypto.Key = Key;
        RijCrypto.IV = IV;

        ICryptoTransform Decryptor = RijCrypto.CreateDecryptor(Key, IV);

        CryptoStream CryptStrm = new CryptoStream(InputFile, Decryptor, CryptoStreamMode.Read);

        String OutputFilePath = Path.GetTempPath() + "myfile.name";
        StreamWriter OutputFile = new StreamWriter(OutputFilePath);

        OutputFile.Write(new StreamReader(CryptStrm).ReadToEnd());

        CryptStrm.Close();
        OutputFile.Close();

        return OutputFilePath;
    }
4

3 回答 3

18

好吧,这里有几件事出了问题。

1.你的IV设置太大了。如果您的密钥大小为 256,则 Rijndael 的 IV 为 16 个字节。如果您尝试使用比这更多的字节设置密钥,您将得到一个异常。IV 大小应设置为 Block size / 8请参阅 MSDN,因此您拥有的 IV 大小是正确的。

  1. 您的填充模式为无。除非您的数据是完全正确的块大小,否则您将遇到问题。您可能想要选择填充模式。
  2. 在加密时完成对加密流的写入后,通常需要调用 FlushFinalBlock,以确保将所有数据写入流中。

我正在使用内存流发布一些示例代码来显示加密和解密。

var tempData = "This is the text to encrypt. It's not much, but it's all there is.";

using (var rijCrypto = new RijndaelManaged())
{
    byte[] encryptedData;
    rijCrypto.Padding = System.Security.Cryptography.PaddingMode.ISO10126;
    rijCrypto.KeySize = 256;

    using (var input = new MemoryStream(Encoding.Unicode.GetBytes(tempData)))
    using (var output = new MemoryStream())
    {
        var encryptor = rijCrypto.CreateEncryptor();

        using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
        {
            var buffer = new byte[1024];
            var read = input.Read(buffer, 0, buffer.Length);
            while (read > 0)
            {
                cryptStream.Write(buffer, 0, read);
                read = input.Read(buffer, 0, buffer.Length);
            }
            cryptStream.FlushFinalBlock();
            encryptedData = output.ToArray();
        }
    }

    using (var input = new MemoryStream(encryptedData))
    using (var output = new MemoryStream())
    {
        var decryptor = rijCrypto.CreateDecryptor();
        using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
        {
            var buffer = new byte[1024];
            var read = cryptStream.Read(buffer, 0, buffer.Length);
            while (read > 0)
            {
                 output.Write(buffer, 0, read);
                 read = cryptStream.Read(buffer, 0, buffer.Length);
            }
            cryptStream.Flush();
            var result = Encoding.Unicode.GetString(output.ToArray());
        }
    }
}
于 2012-03-15T17:37:09.617 回答
3

另一种阅读 CryptoStream 的方法是使用 CopyTo 方法:

...

    using (var output = new MemoryStream())
    {
       cryptStream.CopyTo(output);
       return output.ToArray();
    }

...
于 2020-02-05T11:58:17.407 回答
-1

必须首先指定 KeySize。这看起来像一个错误,例如这有效

            using (var aes = new AesManaged())
            {
                aes.KeySize = 256;
                aes.Mode = CipherMode.CBC;
                aes.IV = iv;
                aes.Key = passwordHash;
                aes.Padding = PaddingMode.PKCS7;

但这不是

            using (var aes = new AesManaged())
            {
                aes.Mode = CipherMode.CBC;
                aes.IV = iv;
                aes.Key = passwordHash;
                aes.Padding = PaddingMode.PKCS7;
                aes.KeySize = 256;
于 2019-01-17T20:08:57.193 回答