为什么我不能使用RijndaelManaged解密数据?

本文关键字:解密 数据 RijndaelManaged 不能 为什么 | 更新日期: 2023-09-27 18:13:59

我正在编写一个像信使一样发送和接收消息的程序,我需要在发送按钮上加密消息,并在收到消息时解密消息。我正在使用RijndaelManaged类和以下方法来加密/解密

 public byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
    {
        // Check arguments.
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("Key");
        byte[] encrypted;
        // Create an RijndaelManaged object
        // with the specified key and IV.
        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = Key;
            rijAlg.IV = IV;
            // Create a decrytor to perform the stream transform.
            ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
            // Create the streams used for encryption.
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }

        // Return the encrypted bytes from the memory stream.
        return encrypted;
    }

 public string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
    {
        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("Key");
        // Declare the string used to hold
        // the decrypted text.
        string plaintext = null;
        // Create an RijndaelManaged object
        // with the specified key and IV.
        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = Key;
            rijAlg.IV = IV;
            // Create a decrytor to perform the stream transform.
            ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
            // Create the streams used for decryption.
            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }
        return plaintext;
    }
下面是我如何调用前面的方法:
  private void SendMessage()
    {
        string str;
        System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
        str = enc.GetString(this.EncryptStringToBytes(this.txtNewMessage.Text, myRijndael.Key, myRijndael.IV ));
        if ( this.remoteClient.Connected && this.txtNewMessage.Text.Trim() != "")
        {
            this.remoteClient.SendCommand(new Proshot.CommandClient.Command(Proshot.CommandClient.CommandType.Message, this.targetIP,str));
            this.txtMessages.Text += this.remoteClient.NetworkName + ": " + this.txtNewMessage.Text.Trim()  + "//---SENT" + Environment.NewLine;
            this.txtNewMessage.Text = "";
            this.txtNewMessage.Focus();
        }
    }

  private void private_CommandReceived(object sender , CommandEventArgs e)
    {
        string str;
        byte[] byteString;

        str =  e.Command.MetaData;
        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
        byteString = encoding.GetBytes(str);

        switch ( e.Command.CommandType )
        {
            case ( CommandType.Message ):
                if ( !e.Command.Target.Equals(IPAddress.Broadcast) && e.Command.SenderIP.Equals(this.targetIP))
                {
                    //myRijndael.Padding = PaddingMode.Zeros;
                    this.txtMessages.Text += e.Command.SenderName + ": " + this.DecryptStringFromBytes(byteString, myRijndael.Key, myRijndael.IV) + "//---Received" + Environment.NewLine;
                    if ( !this.activated)
                    {
                        if(this.WindowState == FormWindowState.Normal || this.WindowState == FormWindowState.Maximized)
                            ShareUtils.PlaySound(ShareUtils.SoundType.NewMessageReceived);
                        else
                            ShareUtils.PlaySound(ShareUtils.SoundType.NewMessageWithPow);
                        this.Flash(this.Handle , FlashMode.FLASHW_ALL , 3);
                    }
                }
                break;
        }    
    }

问题是我在解密加密异常时得到异常-要解密的数据长度无效,我不知道为什么?

为什么我不能使用RijndaelManaged解密数据?

在设置encrypted字节数组之前,可能您应该在加密时冲洗CryptoStream:

...
csEncrypt.FlushFinalBlock();
encrypted = msEncrypt.ToArray();
...

从CryptoStream中提取。FlushFinalBlock方法:

调用Close方法将调用FlushFinalBlock。如果你不打电话关闭,调用FlushFinalBlock来完成缓冲区的刷新。呼叫FlushFinalBlock只在所有流活动完成时。

显然,如果调用Close,所有数据将丢失,因为它也将关闭底层的MemoryStream