Encryption/Decryption of stream.

  • Thread starter Thread starter Martin
  • Start date Start date
M

Martin

Hi
Im trying to make a Client/Server where im going to encrypt the stream but i cant get it to work. I can recieve and send as long as im not trying to send/recieve encrypted. but when i am i cant send, recieve or both.

The Send/Recieve Code is the same on both Server and client.
Send/Recieve Code:

private Stream Net()
{
if(Encrypted)
{
CryptoStream SecStream = new CryptoStream(NetStream,TDes.CreateDecryptor(),CryptoStreamMode.Read);
return SecStream;
}
else
return NetStream;
}

private void GetStreamData(IAsyncResult ar)
{
int intCount;
try
{
lock(Net())
{
intCount = Net().EndRead(ar);
}
if(intCount<1)
{
Client.Close();

if(Disconnected!=null)
{
EventArgs e = new EventArgs();
Disconnected(this, e);
}
}

BuildData(recByte,0,intCount);

AsyncCallback GetStreamDataCallback = new AsyncCallback(GetStreamData);
Net().BeginRead(recByte,0,1024,GetStreamDataCallback,null);
}
catch
{
Client.Close();

if(Disconnected!=null)
{
EventArgs e = new EventArgs();
Disconnected(this, e);
}
}
}

public void Send(string Data)
{
StreamWriter Writer;

if(Encrypted)
{
CryptoStream SecStream = new CryptoStream(NetStream,TDes.CreateEncryptor(),CryptoStreamMode.Write);
Writer = new StreamWriter(SecStream);
}
else
Writer = new StreamWriter(NetStream);

Writer.Write(Data);
Writer.Flush();
}

Code Server:
private void BuildData(byte[] Databyte, int offset, int count)
{
string Data = Encoding.UTF8.GetString(Databyte, offset, count);
string[] DataCmd = Data.Split(':');

if(!Encrypted)
{
switch(DataCmd[0])
{
case "HELO":
{
Send("Welcome");

break;
}
case "DesKey":
{
TDes.GenerateKey();
DesKey = TDes.Key;

Send("DesKey:" + Convert.ToBase64String(DesKey));

break;
}
case "DesIV":
{
TDes.GenerateIV();
DesIV = TDes.IV;

Send("DesIV:" + Convert.ToBase64String(DesIV));

Encrypted = true;

break;
}
}
}
else
{
Send(Data);
}
}

Code Client:
private void BuildData(byte[] Databyte, int offset, int count)
{
string Data = Encoding.UTF8.GetString(Databyte, offset, count);
string[] DataCmd = Data.Split(':');

if(!Encrypted)
{
switch(DataCmd[0])
{
case "Welcome":
{
txtDataRx.Text = "Connected";

break;
}
case "DesKey":
{
//txtDataRx.Text = DataCmd[1];

DesKey = Convert.FromBase64String(DataCmd[1]);
TDes.Key = DesKey;

break;
}
case "DesIV":
{
//txtDataRx.Text = DataCmd[1];

DesIV = Convert.FromBase64String(DataCmd[1]);
TDes.IV = DesIV;

Encrypted = true;

break;
}
}
}
else
{
txtDataRx.Text = Data;
}
}
 
Martin said:
Hi
Im trying to make a Client/Server where im going to encrypt the stream
but i cant get it to work. I can recieve and send as long as im not
trying to send/recieve encrypted. but when i am i cant send, recieve or
both.
Martin -

The problem with feeding a TCP stream directly to a CryptoStream
object is that the CryptoStream has no idea when all of the data is
present for decryption. The CryptoStream will not wait for all of the
data to arrive, it just assumes all the data will be there when it
starts, and throws an Exception when it needs more data that is not
there. Unfortunately, most TCP connections can not deliver the data
quick enough to keep up with the CryptoStream processing, no matter
how fast your network is.

To solve this problem you need a middleman. I use a MemoryStream
to accept the incoming encrypted data from the network. When you know
you have the entire encrpyted data stream in the MemoryStream (send
the data size before sending the data), you can then feed the
MemoryStream into the CryptoStream for decryption.

I demonstrate this in Chapter 17 of my "C# Network Programming"
book. You can download the code for free from the Sybex web site and
check out the examples. Hope this helps solve your problem.

Rich Blum - Author
"C# Network Programming" (Sybex)
http://www.sybex.com/sybexbooks.nsf/Booklist/4176
"Network Performance Open Source Toolkit" (Wiley)
http://www.wiley.com/WileyCDA/WileyTitle/productCd-0471433012.html
 
Back
Top