【问题标题】:"Length of the data to decrypt is invalid." exception during Rijndael decryption“要解密的数据长度无效。” Rijndael解密期间的异常
【发布时间】:2009-05-10 19:40:12
【问题描述】:

我得到“要解密的数据长度无效。”当我尝试解密内存流时出现异常。我是初学者,无法弄清楚什么是错的。怎么了?

public bool EncryptStream()
    {

        string password = @"myKey123"; // Your Key Here
        UnicodeEncoding UE = new UnicodeEncoding();
        byte[] key = UE.GetBytes(password);

        s_EncryptedStream = new MemoryStream();
        int NoOfBytes;
        byte[] b_Buffer = new byte[8192];

        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        RijndaelManaged RMCrypto = new RijndaelManaged();

        s_CrytpoStream = new CryptoStream(s_EncryptedStream,
            RMCrypto.CreateEncryptor(key, key),
            CryptoStreamMode.Write);

        while (s_MemoryStream.Length < s_MemoryStream.Position)
        {
            NoOfBytes = s_MemoryStream.Read(b_Buffer, 0, 8192);
            s_CrytpoStream.Write(b_Buffer, 0, NoOfBytes);
        }

        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        while (s_EncryptedStream.Position < s_EncryptedStream.Length)
        {
            NoOfBytes = s_EncryptedStream.Read(b_Buffer, 0, 8192);
            s_MemoryStream.Write(b_Buffer, 0, NoOfBytes);

        }
        s_CrytpoStream.Flush();
        s_CrytpoStream.Close();

        return true;

    }


    public bool DecryptStream()
    {


        string password = @"myKey123"; // Your Key Here

        UnicodeEncoding UE = new UnicodeEncoding();
        byte[] key = UE.GetBytes(password);

        int NoOfBytes;
        byte[] b_Buffer = new byte[8192];

        s_DecryptedStream = new MemoryStream();


        RijndaelManaged RMCrypto = new RijndaelManaged();

        s_CrytpoStream = new CryptoStream(s_MemoryStream,
            RMCrypto.CreateDecryptor(key, key),
            CryptoStreamMode.Read);

        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        while (s_MemoryStream.Length > s_MemoryStream.Position)
        {
            NoOfBytes = s_CrytpoStream.Read(b_Buffer, 0, 8192);
            s_DecryptedStream.Write(b_Buffer, 0, NoOfBytes);
        }

        s_DecryptedStream.Seek(0, SeekOrigin.Begin);
        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        while (s_DecryptedStream.Position < s_DecryptedStream.Length)
        {
            NoOfBytes = s_DecryptedStream.Read(b_Buffer, 0, 8192);
            s_MemoryStream.Write(b_Buffer, 0, NoOfBytes);

        }

        s_CrytpoStream.Flush();
        s_CrytpoStream.Close();

        return true;

    }

【问题讨论】:

    标签: exception rijndaelmanaged


    【解决方案1】:

    首先,这个 while 循环条件永远不会正确:

    while (s_MemoryStream.Length < s_MemoryStream.Position)
    

    位置怎么会超出长度?

    复制流的常用模式不是使用流的长度,而是重复读取,直到返回的值不是正数。反正你在这段代码中做了两次,你不妨把它封装起来:

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[8192];
        int read;
        while ( (read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            output.Write(buffer, 0, read);
        }
    }
    

    最好使用using 语句来清理字符串。此外,Encoding.Unicode 属性意味着您不必自己创建新的UnicodeEncoding。另外,我通常发现设置Position 属性比使用Seek 更具可读性。最后,如果返回值总是true,那么返回值的方法毫无意义。因此,您的代码将变为:

    public void EncryptStream()
    {
        string password = @"myKey123"; // Your Key Here
        byte[] key = Encoding.Unicode.GetBytes(password);
    
        s_EncryptedStream = new MemoryStream();
        s_MemoryStream.Position = 0;
    
        RijndaelManaged RMCrypto = new RijndaelManaged();
    
        using (Stream crytpoStream = new CryptoStream(s_EncryptedStream,
            RMCrypto.CreateEncryptor(key, key),
            CryptoStreamMode.Write))
        {
            CopyStream(s_MemoryStream, cryptoStream);
        }
    
        s_MemoryStream.Position = 0;
        s_EncryptedStream.Position = 0;
        CopyStream(s_EncryptedStream, s_MemoryStream);
    }
    
    public void DecryptStream()
    {
        string password = @"myKey123"; // Your Key Here
        byte[] key = Encoding.Unicode.GetBytes(password);
    
        s_DecryptedStream = new MemoryStream();
        s_MemoryStream.Position = 0;
    
        RijndaelManaged RMCrypto = new RijndaelManaged();
    
        using (Stream crytpoStream = new CryptoStream(s_MemoryStream,
            RMCrypto.CreateDecryptor(key, key),
            CryptoStreamMode.Read))
        {
            CopyStream(cryptoStream, s_DecryptedStream);
        }
    
        s_DecryptedStream.Position = 0;
        s_MemoryStream.Position = 0;
    
        CopyStream(s_DecryptedStream, s_MemoryStream);
    }
    

    即使修改了这段代码,感觉这里的非局部变量太多了。我不明白为什么 any 应该在实例变量中。将要加密或解密的流作为参数(连同密码)并返回一个内存流,其中包含加密/解密的数据,或者只是一个字节数组。

    【讨论】:

    • 谢谢,这只是一个粗略的代码。我已按照建议进行了更改。我在 CopyStream(cryptoStream, s_DecryptedStream); 中仍然遇到同样的异常;
    • 那么请发布一个简短但完整的程序来演示该问题。我们可以运行一些东西来重现它。
    【解决方案2】:

    读完输入数据后,您可能需要调用CryptoStream 上的FlushFinalBlock 方法。 (即 crytpoStream.FlushFinalBlock() 在 CopyStream 之后)

    【讨论】:

    • 我认为如果你处理 CryptoStream,你不应该需要这样做 - .NET 1.1 中存在一个错误,这意味着它没有刷新 final然后阻止,但它已在 .NET 2.0 中修复。
    【解决方案3】:

    我想出了一个解决方案,并将其发布在我的新博客上

    constotech.blogspot.com/2009/05/net-encryption-using-symmetricalgorithm.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-19
      • 2010-12-22
      • 2010-12-13
      • 2013-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多