5

I'm creating a TCP based chat client. I'm trying to Encrypt some of the data with AES (more security) I have a AES encryption class and it uses UTF-8 by default as the out going and incoming Encoding type. But for some reason when i pass the information over the TCPClient (using UTF-8) and get it the other side it is throwing an error:

`System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid.
   at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.FlushFinalBlock()`

So I recreated the problem without using the TCP client, just taking the AES encrypted data and putting it through a UTF-8 Encoding system that gets the string of the byte array then re-gets the byte array all using UTF-8 (basically the same thing as what happens over the network (without the string))

This method works:

        string dataToEncrypt = "Hello World";
        byte[] key = Encryption.AesEncryption.GenerateKey(32);
        byte[] iv = Encryption.AesEncryption.GenerateKey(16);

        byte[] encrypted = Encryption.AesEncryption.EncryptString(dataToEncrypt, key, iv);

        string decrypted = Encryption.AesEncryption.DecryptedBytes(encrypted, key, iv);

The method doesn't work (throws the error from above)

        Encoding encoding = Encoding.UTF8;

        string dataToEncrypt = "Hello World";
        byte[] key = Encryption.AesEncryption.GenerateKey(32);
        byte[] iv = Encryption.AesEncryption.GenerateKey(16);

        byte[] encrypted = Encryption.AesEncryption.EncryptString(dataToEncrypt, key, iv);

        string encstring = encoding.GetString(encrypted);

        byte[] utf8encrypted = encoding.GetBytes(encstring);

        string decrypted = Encryption.AesEncryption.DecryptedBytes(utf8encrypted, key, iv);

What am i doing wrong?

This is my Encryption Class:

public sealed class AesEncryption
{
    private byte[] Key;

    public Encoding Encoder = Encoding.UTF8;

    public AesEncryption(byte[] key)
    {
        Key = key;
    }

    public byte[] Encrypt(string text, byte[] iv)
    {
        var bytes = Encoder.GetBytes(text);
        var rm = new RijndaelManaged();
        var encrypter = rm.CreateEncryptor(Key, iv);
        var ms = new MemoryStream();
        var cs = new CryptoStream(ms, encrypter, CryptoStreamMode.Write);
        cs.Write(bytes, 0, bytes.Length);
        cs.FlushFinalBlock();
        var output = ms.ToArray();
        cs.Close();
        ms.Close();
        return output;
    }

    public string Decrypt(byte[] encrypted, byte[] iv)
    {
        var ms = new MemoryStream();
        var cs = new CryptoStream(ms,
            new RijndaelManaged().CreateDecryptor(Key, iv),
            CryptoStreamMode.Write);
        cs.Write(encrypted, 0, encrypted.Length);
        cs.FlushFinalBlock();
        var output = ms.ToArray();
        cs.Close();
        ms.Close();
        return Encoder.GetString(output);
    }

    public static byte[] EncryptString(string text, byte[] key, byte[] iv)
    {
        var ec = new AesEncryption(key);
        return ec.Encrypt(text, iv);
    }

    public static string DecryptedBytes(byte[] encrypted, byte[] key, byte[] iv)
    {
        var ec = new AesEncryption(key);
        return ec.Decrypt(encrypted, iv);
    }

    public static byte[] GenerateKey(int length)
    {
        Random rnd = new Random();

        var chars = "1!2@3#4$5%6^7&8*9(0)-_=+qQwWeErRtTyYuUiIoOpP[{]}\\|aAsSdDfFgGhHjJkKlL;:'\"zZxXcCvVbBnNmM,<.>/?".ToCharArray();

        string randomizedKey = "";

        for (int i = 0; i < length; i++)
        {
            randomizedKey += chars[rnd.Next(0, chars.Length)];
        }
        return randomizedKey.ToByteArray();
    }
}
2
  • That is the second version of the AESEncryption class, the other one did the same thing except it was using "using" statements for the MemoryStream, CryptoStream and RijndealManaged references. Commented Oct 30, 2014 at 22:44
  • Since the first method works, why are you trying to use the second method (which does not and cannot)? Why not just use the first, correct method? Commented Oct 30, 2014 at 23:08

1 Answer 1

3

UTF-8 does not perfectly represent the bytes. The short and simple answer is: Transmit bytes, not a UTF-8 string. If you must have a string, encode it in Base64.

Sign up to request clarification or add additional context in comments.

8 Comments

It may not perfectly represent bytes, but which encoding does? I need to specify an encoding when reading the bytes through the TCP Client (seeing as i'm using Async) EDIT: Which would be best*
Best would be altering your usage of TCP to allow byte transmission. Second best is Base64 Encoding: stackoverflow.com/questions/11743160/…
The TCP client does use bytes but you need an encoding to read from the network stream, if one isn't supplied it won't work.
@Mr.Sir.AlecJr.: You're being stubborn.
@Mr.Sir.AlecJr. I recommend you look into Socket networking rather than using TCPClients, it might make things work out better for you. (Just an option).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.