0

我正在开发一个像信使一样发送和接收消息的程序,我需要在发送按钮上加密消息并在收到消息时解密消息。我正在使用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;
        }    
    }

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

4

1 回答 1

1

Probably you should flush your CryptoStream while encrypting before you set the encrypted byte array:

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

An extract from CryptoStream.FlushFinalBlock Method:

Calling the Close method will call FlushFinalBlock. If you do not call Close, call FlushFinalBlock to complete flushing the buffer. Call FlushFinalBlock only when all stream activity is complete.

Obviously, if you call Close, all data will be lost, as it will close the underlying MemoryStream as well.

于 2012-09-11T05:36:05.980 回答