通过System.Net.Socket发送数据后,使用Rijndael解密数据时出现问题

本文关键字:数据 解密 Rijndael 问题 使用 Net System Socket 通过 | 更新日期: 2023-09-27 18:29:57

我在YouTube上学习了一个教程,http://tinyurl.com/ljvzjqk和http://tinyurl.com/os7vlgr,并尝试在我正在进行的客户端/服务器项目中实现这一点。我可以在客户端程序中对字符串进行加密和解密,但当服务器中接收到数据时,它无法正确解密。

在调试时,我可以看到携带数据的字节[]两端完全相同。

在这两个程序中,这都是在类中声明的:

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

服务器:

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);
    }

客户:

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);
    }

客户端程序输出:

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:

服务器程序输出:

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

正如你所看到的,服务器中的加密字符串等于客户端中的加密串,所以我想这与rjnObj有关,并且这个对象的两端并不相同。

这里给出的代码是我为提出这个问题而创建的一个新解决方案。我使用了PaddingMode.Zeros,因为当我尝试PKCS7时,我得到了一个异常。

在服务器代码中,我将另一个字节[]dataReceived2设置为接收字节[]的确切长度。我发现了通过网络发送加密数据的其他代码示例,但这些示例使用TcpClient和NetworkStream。在我为一个学校项目开发的解决方案中,我使用的是Sockets,我真的不想重写这个解决方案。

如果森博迪能帮我做这件事,那就太好了!谢谢

通过System.Net.Socket发送数据后,使用Rijndael解密数据时出现问题

尝试使用相同的IV。我相信当您创建Rijndael.Create()的新实例时,Key和IV将随机生成。你只设置了密钥,但要使这项工作,你还需要使用相同的IV.

在客户端上,您使用相同的Rijndael实例,因此加密和解密工作正常。

您可能想在这里查看Rijndael类使用的文档和示例。我喜欢的是使用语句。它看起来更干净,因为溪流一旦不再使用就关闭了。

服务器中的Decrypt方法根本没有任何意义。正如您现在所做的,您应该将cs Stream读取到明文数组中。或者,您可以对流进行不同的分层,将密文写入csStream,并从底层内存流中检索明文。我认为后一种方法更干净、更容易。