Friday, June 27, 2008

The basics of secure data exchange under TCP


Doing data exchange in plain text is very convenient and easy to implement but what can you do to prevent eavesdropping, tampering, and message forgery of the data you send back and forth? Here's where secure communication comes into play. At present the most common secure communication method is using Transport Layer Security (TLS) or Secure Sockets Layer (SSL). In web context you can see secure data exchange in action when browsing web-sites with HTTPS prefix

In .NET framework secure communications can be done with SslStream class. It can use both TLS and SSL protocols.

TLS and SSL for authentication process use public key infrastructure or PKI. It requires certificates.

Here's nice explanation how to create certificate using makecert utility

After reading and doing what was said in the above mentioned blogpost we should end up with 2 installed certificates. They're depicted on the picture below.

The certificate we'll use will be "vadmyst-enc".

SslStream gives you the look and feel of a common .NET stream.

So, what are the basic steps to start secure communication with SslStream?
Very often the communication happens between server (e.g web server) and client (e.g. browser).
Here are the steps for the server side:

  • Start listening on specific address and port

  • When connection is accepted wrap obtained NetworkStream with SslStream

  • Call SslStream::AuthenticateAsServer

  • Start doing I/O (in our case that's basic echo server

In code it looks like this:
TcpListener listener = new TcpListener(ipEndpoint);
listener.Start(5);
TcpClient tcpClient = listener.AcceptTcpClient();

SslStream secureStream = new SslStream(tcpClient.GetStream(), false);

secureStream.AuthenticateAsServer(serverCertificate);
//use anonymous delegate for simplicity
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object unused)
{
//simple echo server
byte[] tempBuffer = new byte[1024];
int read = 0;
try
{
while ((read = secureStream.Read(tempBuffer, 0, tempBuffer.Length)) > 0)
{
secureStream.Write(tempBuffer, 0, read);
}
}
finally
{
secureStream.Close();
}
}), null);
serverCertificate is obtained from certificate storage on the local machine:
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate serverCertificate = null;
for (int i = 0; i < store.Certificates.Count; i++)
{
serverCertificate = store.Certificates[i];
if (serverCertificate.Subject.Contains("vadmyst-enc"))
break;
}
store.Close();
In this post I'll will not cover usage of client certificates to perform client authentication for the simplicity's sake. Client will only authenticate server.
The steps required by the client:
  • Open TCP connection to the remote server

  • Wrap obtained NetworkStream with SslStream instance

  • Call SslStream::AuthenticateAsClient

  • Begin do the I/O

Source code below demonstrates basic TCP client that transfers data in a secure way.
TcpClient client = new TcpClient();
client.Connect(endPoint);
SslStream sslStream = new SslStream(client.GetStream(), false);
sslStream.AuthenticateAsClient("vadmyst-enc");

byte[] plaintext = new byte[5*1024 + 35];
byte[] validation = new byte[plaintext.Length];

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetNonZeroBytes(plaintext);

sslStream.Write(plaintext);
sslStream.Flush();

int read = 0;
int totalRead = 0;
while( (read = sslStream.Read(validation, totalRead,
validation.Length - totalRead)) > 0)
{
totalRead += read;
if (totalRead == plaintext.Length)
break; //we've received all sent data
}
//check received data
for(int i=0; i < plaintext.Length; i++)
{
if ( validation[i] != plaintext[i] )
throw new InvalidDataException("Data is not the same");
}
sslStream.Close();

SslStream appeared in .NET framework on version 2.0. As you can see doing secure communications with it is very easy. However, there are number of situations that require additional coding: client authentication using client certificates, using other algorithms when doing secure I/O. I will cover these advanced topics on the next posts. Stay tuned!

11 comments:

  1. I could give my own opinion with your topic that is not boring for me.

    ReplyDelete
  2. Thank you very very much for this post - I've been stuck in this very problem for about 2 weeks and your information sorted me out perfectly :-D

    ReplyDelete
  3. very good
    ur blog is so good by we want more than this
    i invite u to visit my blog
    Protection Blog
    http;//dr-virus.blogspot.com

    ReplyDelete
  4. Nice article, helped me solve a problem I was having. Thanks

    ReplyDelete
  5. Understandably your article helped me very much in my college assignment. Hats afar to you post, choice look audacious in behalf of more cognate articles promptly as its sole of my choice topic to read.

    ReplyDelete
  6. Very Important and nice topic.
    Step By Step to be the most professional.
    Thank You...

    ReplyDelete
  7. Hi,
    Thanks for the post.

    How can we implement SSL stream with IOCP (SocketAsyncEventArgs)
    I could not find any samples over the internet. please provide your feedback on this.

    Thaks

    ReplyDelete
  8. There is no "open" implementation TLS based on IOCP (SocketAsyncEventArgs) that I know of. You should create your own, using TLS RFC as a spec

    ReplyDelete
  9. Thanks Vadym for the quick reply.
    how can we build high performance secured socket server? any thoughts.

    ReplyDelete
  10. You can surely start with this library http://www.mentalis.org/soft/projects/ssocket/.

    ReplyDelete