通过 TCP 发送加密数据(“Bad Data”异常)
Sending encrypted data via TCP (“Bad Data” exception)
如何从 tpc 客户端向 tcp 服务器发送非法字符。
这是加密乱码的示例:
https://i.stack.imgur.com/wfZdm.png
我如何将这段乱码发送到我的客户端或服务器?
这是我的加解密密码
public static string Decrypt(string data)
{
byte[] dataToDecrypt = StringToByteArray(data);
byte[] decryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(privateKey);
decryptedData = rsa.Decrypt(dataToDecrypt, false);
}
UnicodeEncoding byteConverter = new UnicodeEncoding();
return ByteArrayToString(decryptedData);
}
public static string Encrypt(string data, string publicKey)
{
UnicodeEncoding byteConverter = new UnicodeEncoding();
byte[] dataToEncrypt = StringToByteArray(data);
byte[] encryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(publicKey);
encryptedData = rsa.Encrypt(dataToEncrypt, false);
}
return ByteArrayToString(encryptedData);
}
public static byte[] StringToByteArray(string data)
{
return Encoding.ASCII.GetBytes(data);
}
public static string ByteArrayToString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
我做到了,因此客户端和服务器共享彼此的 public 密钥,但我收到异常 "Bad data"。还有一件事,如果我从客户端向服务器发送加密数据,该数据为 128 字节,服务器仅接收 78 字节,例如
您的代码有一些问题:
- 你根本不应该使用
String
。
String
用于文本,而不是任意二进制数据(我假设您从 C 或 PHP 那里得到了这种印象,其中它们的字符串类型实际上只是 - 或 thin-wrappers 的同义词一个字节数组)。
- 保留从
rs.Encrypt
获得的 Byte[]
缓冲区,并将其直接传递给您正在使用的 Socket
、TcpClient
或 NetworkStream
。不过,您需要定义一个带有长度前缀的二进制协议。
Encoding.ASCII.GetBytes
会将 String data
实例中的 UTF-16LE 编码字符转换为 7 位 ASCII,it does this by replacing characters with values above 0x7F
和 '?'
- 这不是您想要的!(这就是导致屏幕上出现垃圾输出的原因:那些 "illegal characters" 是高于 0x7F
的字节值,不在 ASCII 7 位范围。来自文档:
It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character.
如果您真的想使用人类可读的文本通过网络传输数据,请使用 Base64 编码:Convert.ToBase64String( Byte[] buffer )
并在接收端使用 Convert.FromBase64String( String s )
将其转换回来- 但您仍然需要为数据添加长度前缀或定界。
如何从 tpc 客户端向 tcp 服务器发送非法字符。 这是加密乱码的示例:
https://i.stack.imgur.com/wfZdm.png
我如何将这段乱码发送到我的客户端或服务器?
这是我的加解密密码
public static string Decrypt(string data)
{
byte[] dataToDecrypt = StringToByteArray(data);
byte[] decryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(privateKey);
decryptedData = rsa.Decrypt(dataToDecrypt, false);
}
UnicodeEncoding byteConverter = new UnicodeEncoding();
return ByteArrayToString(decryptedData);
}
public static string Encrypt(string data, string publicKey)
{
UnicodeEncoding byteConverter = new UnicodeEncoding();
byte[] dataToEncrypt = StringToByteArray(data);
byte[] encryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(publicKey);
encryptedData = rsa.Encrypt(dataToEncrypt, false);
}
return ByteArrayToString(encryptedData);
}
public static byte[] StringToByteArray(string data)
{
return Encoding.ASCII.GetBytes(data);
}
public static string ByteArrayToString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
我做到了,因此客户端和服务器共享彼此的 public 密钥,但我收到异常 "Bad data"。还有一件事,如果我从客户端向服务器发送加密数据,该数据为 128 字节,服务器仅接收 78 字节,例如
您的代码有一些问题:
- 你根本不应该使用
String
。String
用于文本,而不是任意二进制数据(我假设您从 C 或 PHP 那里得到了这种印象,其中它们的字符串类型实际上只是 - 或 thin-wrappers 的同义词一个字节数组)。
- 保留从
rs.Encrypt
获得的Byte[]
缓冲区,并将其直接传递给您正在使用的Socket
、TcpClient
或NetworkStream
。不过,您需要定义一个带有长度前缀的二进制协议。 Encoding.ASCII.GetBytes
会将String data
实例中的 UTF-16LE 编码字符转换为 7 位 ASCII,it does this by replacing characters with values above0x7F
和'?'
- 这不是您想要的!(这就是导致屏幕上出现垃圾输出的原因:那些 "illegal characters" 是高于0x7F
的字节值,不在 ASCII 7 位范围。来自文档:It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character.
如果您真的想使用人类可读的文本通过网络传输数据,请使用 Base64 编码:
Convert.ToBase64String( Byte[] buffer )
并在接收端使用Convert.FromBase64String( String s )
将其转换回来- 但您仍然需要为数据添加长度前缀或定界。