我正在做一个TCP服务器和客户端应用程序。我需要加密和解密消息,但在此之前我需要创建一个与AES算法一起使用的对称密钥。我在服务器和客户端之间使用了Diffie-Hellman公钥交换。但是,当我使用公钥作为参数时,我收到参数不正确的错误。
我使用Receive和Send在服务器和客户端之间传输数据。
static byte[] Receive(NetworkStream netStream)
{
try
{
byte[] receive = new byte[STD_MSG_SIZE];
int length = netStream.Read(receive, 0, receive.Length);
string x = Convert.ToBase64String(receive, 0, length);
return Encoding.UTF8.GetBytes(x);
}
catch (Exception except)
{
Console.WriteLine("Error at receive\n" + except.Message + "\n" + except.StackTrace);
return null;
}
}
static void Send(NetworkStream netStream, byte[] message)
{
try
{
byte[] send = message;
netStream.Write(send, 0, send.Length);
}
catch (Exception except)
{
Console.WriteLine("Error at send\n" + except.Message + "\n" + except.StackTrace);
}
}
这是客户端中的代码,我生成公钥,将其发送到服务器,然后从服务器接收公钥。
TcpClient client = new TcpClient();
client.Connect(IPAddress.Parse(STD_IP), STD_PORT);
ECDiffieHellmanCng alice = new ECDiffieHellmanCng();
alice.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
alice.HashAlgorithm = CngAlgorithm.Sha256;
byte[] publicKey = alice.PublicKey.ToByteArray();
NetworkStream ns = client.GetStream();
Send(ns, publicKey);
byte[] data = Receive(ns);
textBox1.Text = Convert.ToBase64String(data);
byte[] simKey = alice.DeriveKeyMaterial(ECDiffieHellmanCngPublicKey.FromByteArray(data, CngKeyBlobFormat.EccPublicBlob));
这是Server中的代码。我在表单中使用文本框来显示公钥。
TcpListener tcpListener = new TcpListener(IPAddress.Parse(STD_IP), STD_PORT);
tcpListener.Start();
ECDiffieHellmanCng bob = new ECDiffieHellmanCng();
bob.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
bob.HashAlgorithm = CngAlgorithm.Sha256;
byte[] publicKey = bob.PublicKey.ToByteArray();
TcpClient client = tcpListener.AcceptTcpClient();
NetworkStream ns = client.GetStream();
byte[] data = Receive(ns);
textBox1.Text = Convert.ToBase64String(data);
Send(ns, publicKey);
byte[] simKey = bob.DeriveKeyMaterial(ECDiffieHellmanCngPublicKey.FromByteArray(data, CngKeyBlobFormat.EccPublicBlob));
当我评论simKey时,我从客户端和服务器中的数据中获取了这些值。
客户端的文本框:UlVOTE5VSUFBQUFBdXZXTXgzdHFUb0hZVGY0NnFyNlovVWJuRCtUMlZqMTVGZEN5RmIrYnFLRHN3WTZ5clJIemlNblAzYUJDZUpaaW5oVTN6ODFVUWZZaWNiRUNSaUR4NFNJQXBFdE5uYzl0Z1VOV01qNTllSVRaRCtOdGp2V3lIMzZWR21FdDBUSzFKUEx1UTBFZ2tXTXRFU0E1dTJWSkxoWk1FU2NKQ2tXMUhkc0hGWUQwUmFldHJ3RT0 =
服务器文本框: UlVOTE5VSUFBQUFCcWQ3TnZzK0pFQ3BydFFYK2k4T1ErN3pGNXZQSzh6S1I3UEJvUzN3VERkdFB0N05nM2tNWi9TTXkzVFRpZ0JBMmhQdlJJakhObWJ1WlZhc3ZFUTZMUnkwQVdockhMcjh6SzlSTUtsbloxWnVwcDFqMGh3cTNNK04yNXlraUNrMk51b1BVSlZVQkJXOFM4TWQ2eEp6NzQvbHNHSWY1Sy9MUUxnZEp3OUhad2pNcW85dz0 =
答案 0 :(得分:0)
令我惊讶的是,只要缓冲区足够大以容纳公钥,Read
方法的使用就是正确的。
问题是你然后在Receive
方法中对结果进行base64编码,该方法应该只返回字节。除了弄乱你的设计 - 如果一个读取数据的方法也对它进行编码,那绝对不是最少惊喜 - 这也会使解析公钥失败。
可以为文本框添加64位编码。但只要您不需要二进制编码,就应该将其排除在外。或至少在使用前解码它。