dissar
dissar

Reputation: 3

Issues with decrypting data with Rijndael after sending through System.Net.Socket

I followed a tutorial from YouTube, http://tinyurl.com/ljvzjqk and http://tinyurl.com/os7vlgr, and tried to implement this in a client/server-project I am working on. I can encrypt and decrypt strings in the client program just fine, but when the data is received in the server it does not decrypt it correctly.

While debugging I could see that the byte[] carrying the data is exactly the same in both ends.

In both programs, this is declared in the class:

static SymmetricAlgorithm rjnObj;
static byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };

Server:

static void Main(string[] args)
    {
        rjnObj = Rijndael.Create();
        rjnObj.Padding = PaddingMode.Zeros;
        rjnObj.Key = Key;

        Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1980);

        serverSocket.Bind(localEP);
        serverSocket.Listen(10);
        serverSocket = serverSocket.Accept();
        while(true)
        {
            byte[] dataReceived = new byte[1024];
            int lengthOfData = serverSocket.Receive(dataReceived);
            byte[] dataReceived2 = new byte[lengthOfData];
            for (int i = 0; i < lengthOfData; i++)
            {
                dataReceived2[i] = dataReceived[i];
            }
            Console.WriteLine("Received: {0}", Encoding.UTF8.GetString(dataReceived2));
            Console.WriteLine("Decrypted: {0}", Decrypt(dataReceived2));
        }
    }
    public static string Decrypt(byte[] cipherbytes)
    {
        System.IO.MemoryStream ms = new System.IO.MemoryStream(cipherbytes);
        CryptoStream cs = new CryptoStream(ms, rjnObj.CreateDecryptor(), CryptoStreamMode.Read);

        cs.Read(cipherbytes, 0, cipherbytes.Length);
        byte[] plainBytes = ms.ToArray();
        cs.Close();
        ms.Close();

        return Encoding.UTF8.GetString(plainBytes);
    }

Client:

static void Main(string[] args)
    {
        rjnObj = Rijndael.Create();
        rjnObj.Padding = PaddingMode.Zeros;
        rjnObj.Key = Key;

        Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1980);

        try
        {
            clientSocket.Connect(serverEP);
            Console.WriteLine("Connected to {0}.", clientSocket.RemoteEndPoint);

            while(true)
            {
                Console.Write("String to send: ");
                byte[] dataToSend = Encrypt(Console.ReadLine());
                clientSocket.Send(dataToSend);

                Console.WriteLine("Encrypted string: {0}", Encoding.UTF8.GetString(dataToSend));
                Console.WriteLine("Decrypted string: {0}", Decrypt(dataToSend));
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Something went wrong...");
            Console.WriteLine(e.ToString());
            Console.ReadKey();
        }
    }
    public static byte[] Encrypt(string s)
    {
        byte[] plainBytes = Encoding.UTF8.GetBytes(s);
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        CryptoStream cs = new CryptoStream(ms, rjnObj.CreateEncryptor(), CryptoStreamMode.Write);

        cs.Write(plainBytes, 0, plainBytes.Length);
        cs.Close();
        byte[] cipherbytes = ms.ToArray();
        ms.Close();

        return cipherbytes;
    }
    public static string Decrypt(byte[] cipherbytes)
    {
        System.IO.MemoryStream ms = new System.IO.MemoryStream(cipherbytes);
        CryptoStream cs = new CryptoStream(ms, rjnObj.CreateDecryptor(), CryptoStreamMode.Read);

        cs.Read(cipherbytes, 0, cipherbytes.Length);
        byte[] plainBytes = ms.ToArray();
        cs.Close();
        ms.Close();

        return Encoding.UTF8.GetString(plainBytes);
    }

Output from client-program:

Connected to 127.0.0.1:1980.
String to send: Hello server!
Encrypted string: ?*?8?2?HfG▲z  ?K
Decrypted string: Hello server!
String to send:

Output from server-program:

Received: ?*?8?2?HfG▲z  ?K
Decrypted: E??diQ♣?ZX??♂?z

As you can see, the encrypted string in the server is equal to the encrypted string in the client, so I guess it has something to do with rjnObj, and that this object is not identical in both ends.

The code given here is a new solution I created to ask this question. I have used PaddingMode.Zeros, because when I tried PKCS7, I got an exception.

In the server-code I made another byte[] dataReceived2 to be the exact length of the received byte[]. I have found other examples of code that sends encrypted data over a network, but these examples use TcpClient and NetworkStream. In the solution I am working on for a school project, I am using Sockets and I really don't want to rewrite the solution.

If sombody can help me with this, that would be great! Thanks!

Upvotes: 0

Views: 211

Answers (2)

pepo
pepo

Reputation: 8877

Try to use the same IV. I believe that when you create a new instance of Rijndael.Create(), Key and IV will be randomly generated. You only set Key, but to make this work you also need to use the same IV.

On the client you use the same instance of Rijndael therefore encrypt and decrypt are working fine.

You might want to look at the documentation and example of Rijndael class usage here. What I like about it are using statements. It looks cleaner as the streams are closed as soon as they are not used anymore.

Upvotes: 1

President James K. Polk
President James K. Polk

Reputation: 41967

Your Decrypt method in the server doesn't make any sense at all. As you've done it now you should be reading from the cs Stream into the plaintext array. Or you can layer the streams differently and write the ciphertext into a cs Stream and retrieve the plaintext from the underlying memory stream. I think the latter method is cleaner and easier.

Upvotes: 1

Related Questions