我按照YouTube上的教程http://tinyurl.com/ljvzjqk和http://tinyurl.com/os7vlgr,尝试在我正在处理的客户端/服务器项目中实现此功能。 我可以很好地加密和解密客户端程序中的字符串,但是当在服务器中收到数据时,它不会正确解密它。
调试时我可以看到携带数据的byte []在两端完全相同。
在这两个程序中,这是在类中声明的:
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时,我得到了一个例外。
在服务器代码中,我将另一个byte [] dataReceived2作为接收字节[]的确切长度。 我找到了通过网络发送加密数据的其他代码示例,但这些示例使用TcpClient和NetworkStream。 在我正在为一个学校项目工作的解决方案中,我正在使用套接字,我真的不想重写解决方案。
如果sombody可以帮助我,那就太好了!谢谢!
答案 0 :(得分:1)
服务器中的Decrypt方法根本没有任何意义。正如您现在所做的那样,您应该将从 cs Stream 读取到明文数组中。或者,您可以以不同方式对流进行分层,并将将密文写入cs Stream,并从底层内存流中检索明文。我认为后一种方法更清洁,更容易。
答案 1 :(得分:1)
尝试使用相同的IV。我相信当您创建Rijndael.Create()
的新实例时,将随机生成Key和IV。您只需设置Key,但要使其工作,您还需要使用相同的IV。
在客户端上,您使用相同的Rijndael
实例,因此加密和解密工作正常。
您可能希望查看Rijndael
班级使用here的文档和示例。我喜欢它的是使用语句。它看起来更干净,因为它们一旦不再使用就会关闭。