Я студент факультета компьютерных наук, и это мой второй проект на c #, поэтому я к этому еще не привык, и это мой второй вопрос по stackoverflow ... Мне нужно создать программу с сервером и клиентом, но ихсвязь должна быть безопасной (я использовал Диффи-Хеллмана и AES). Моя программа зависает, когда я пытаюсь прочитать отправленное сообщение через NetworkStream, программа работает нормально, если я добавлю показывать какое-либо сообщение с помощью MessageBox, перед чтением из потока. Также есть ли способ для клиента и сервера генерировать один и тот же AES.IV, кроме моей реализации global IV?
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using System.Linq;
namespace Kodiranje
{
public partial class Form1 : Form
{
const int port = 22222;
const string ip = "127.0.0.1";
IPAddress ipServer = IPAddress.Parse(ip);
TcpListener server = null;
TcpClient client = null;
Thread thServer = null;
NetworkStream dataStream = null;
string receivedMessage = "";
bool? izbira = null;
Aes myAes = Aes.Create();
byte[] iv = null;
public Form1()
{
InitializeComponent();
iv = myAes.IV;
thServer = new Thread(new ThreadStart(startServer));
thServer.IsBackground = true;
thServer.Start();
myAes.Padding = PaddingMode.PKCS7;
iv = myAes.IV;
}
void startServer() {
server = new TcpListener(ipServer, port);
server.Start();
textBox4.Invoke(new Action(() => textBox4.AppendText("Strežnik: zagnan na: IP: " + ip + ", port:" + port)));
client = new TcpClient();
client = server.AcceptTcpClient();
NetworkStream dataStream = client.GetStream();
textBox4.Invoke(new Action(() => textBox4.AppendText(Environment.NewLine + "Strežnik: Sprejet nov uporabnik")));
if (izbira == true)
{
byte[] serverPublicKey;
ECDiffieHellmanCng serverDH = new ECDiffieHellmanCng();
serverDH.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
serverDH.HashAlgorithm = CngAlgorithm.Sha256;
serverPublicKey = serverDH.PublicKey.ToByteArray();
byte[] message = new byte[1024];
while (!dataStream.DataAvailable) { }
if (dataStream.DataAvailable)
dataStream.Read(message, 0, message.Length);
byte[] serverCommoneKey = serverDH.DeriveKeyMaterial(CngKey.Import(message, CngKeyBlobFormat.EccPublicBlob));
textBox4.Invoke(new Action(() => textBox4.AppendText(Environment.NewLine + "Strežnik: Dobil sem sporočilo: " + receivedMessage)));
dataStream.Write(serverPublicKey, 0, serverPublicKey.Length);
message = new byte[1024];
myAes = Aes.Create();
myAes.Padding = PaddingMode.PKCS7;
myAes.Key = serverCommoneKey;
myAes.IV = iv;
ICryptoTransform encryptor = myAes.CreateEncryptor(myAes.Key, iv);
byte[] encrypted;
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write("Serbus deda");
}
encrypted = msEncrypt.ToArray();
int s = encrypted.Length;
MessageBox.Show(""); // freezes without message
dataStream.Write(encrypted, 0, encrypted.Length);
}
}
}
else {
byte[] message = new byte[1024];
message = Encoding.UTF8.GetBytes("serbus");
dataStream.Write(message, 0, message.Length);
}
}
void button1_Click(object sender, EventArgs e) { // happens when client connects to the server
if (izbira == null) {
textBox4.Invoke(new Action(() => textBox4.AppendText(Environment.NewLine + "Izbrati morate ali boste datoteko prenesli ali poslali!")));
return;
}
this.button1.Enabled = false;
client = new TcpClient();
IPAddress insertedIp = IPAddress.Parse(textBox1.Text);
byte[] clientPublicKey;
ECDiffieHellmanCng clientDH = new ECDiffieHellmanCng();
clientDH.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
clientDH.HashAlgorithm = CngAlgorithm.Sha256;
clientPublicKey = clientDH.PublicKey.ToByteArray();
client.Connect(insertedIp, Convert.ToInt32(textBox3.Text));
dataStream = client.GetStream();
if (izbira == true)
{
dataStream.Write(clientPublicKey, 0, clientPublicKey.Length);
byte[] message = new byte[1024];
MessageBox.Show(""); // freezes without message
while (true)
{
if (dataStream.DataAvailable)
{
dataStream.Read(message, 0, message.Length);
textBox4.Invoke(new Action(() => textBox4.AppendText(Environment.NewLine + "Client: Dobil sem sporočilo: " + receivedMessage)));
break;
}
}
byte[] clientCommoneKey = clientDH.DeriveKeyMaterial(CngKey.Import(message, CngKeyBlobFormat.EccPublicBlob));
byte[] encryptedMessage = new byte[16];
while (!dataStream.DataAvailable) { }
MessageBox.Show(""); // freezes without message
dataStream.Read(encryptedMessage, 0, encryptedMessage.Length);
myAes = Aes.Create();
myAes.Padding = PaddingMode.PKCS7;
myAes.Key = clientCommoneKey;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = myAes.CreateDecryptor(myAes.Key, iv);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(encryptedMessage))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
string plaintext;
plaintext = srDecrypt.ReadToEnd();
MessageBox.Show("Sprejeto sporočilo " + plaintext);
}
}
}
}
else {
byte[] message = new byte[1024];
//MessageBox.Show("Serbus");
while (!dataStream.DataAvailable)
{ }
dataStream.Read(message, 0, message.Length);
receivedMessage = Encoding.UTF8.GetString(message);
textBox4.Invoke(new Action(() => textBox4.AppendText(Environment.NewLine + "Strežnik: Dobil sem sporočilo: " + receivedMessage)));
}
}
void buttonUpload_Click(object sender, EventArgs e) {
izbira = true;
this.buttonDownload.Enabled = false;
}
void buttonDownload_Click(object sender, EventArgs e) {
izbira = false;
this.buttonUpload.Enabled = false;
this.button2.Text = "Prenesi";
}
}
}