Tuesday, July 10, 2012

SslStream

SslStream is a nice new feature of .NET 4.0, before that you had to implement the security layer all by yourself, I've seen a project written by Tamir Gal doing just that while searching for other implementations of ssl, another interesting project is Granados.

I had some experience in the past implementing encryption and hashing on an old project in the pre .net era many years ago, the company used DCOM for remoting and while that was a common practice at the time it was very slow, so I've decided to implement a RESTful interface, needless to say the speed improvement was tremendously faster, the application load was about a minute and was shortened to about 2 seconds, working in the application was a lot quicker and we could do more work with the same amount of typists, which was a real boom in productivity.


Enough nostalgia :-)


I've written a simple client/server chat, I especially wanted to use something more than a string transfer, so I used BinaryFormatter and serialized a class containing the message to transfer, this way its way easier to extend this little demo to something useful, feel free to use it. 


The application is written synchronously, I wanted it to be as clear as possible and starting to track threads and callbacks might complicate some things, the application is for a demo, if you're planning to use parts of it, you'll have to rewrite some code for it to be efficient.


Also, the application is not structured appropriately, I've put all the common logic inside the ChatMessages library, but it should be in a separate library and ChatMessages should be in its own library, take that into account if you're using this demo in any other way than it was intended.


After the basics worked, I've added the SslStream layer, I've used a self signed certificate from pluralsight's selfcert application.


Started the program and... got an error "The server mode SSL must use a certificate with the associated private key."

Wait, I created a private key, it is evident by the password I put in.

Turns out .NET can't use a certificate off the disk, its not secured, so I imported the certificate.

This time the client threw an exception "The remote certificate is invalid according to the validation procedure."

If the certificate is not trusted, SslStream won't let you use it, so you can either trust it or write a local override, if you do decide to write an override, be sure to be as specific as possible, such as using the certificate's hash, otherwise you open a security risk.



static bool RemoteCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
   if (certificate.GetCertHashString() == "48D5760D449114D08E0297AD9BDB29028326BD96")
      return true;
   return false;
}

We put this in the class constructor for the client

Stream clientstream = new SslStream(client.GetStream(), true, RemoteCertificateValidation, null);

Ok, the first part is now working, I can see the connection being made, the SslStream returns authentication information but all of the sudden the application is frozen, the Read method is not returning as before, its blocking.

I've tried setting the underlying TCP clients to timeout, it only resulted in exceptions in the ssl layer and I couldn't find any way of peeking inside the ssl layer's buffer, see if any bytes are available, so I wrote a StreamReadAsync class which will buffer the Reads and will not block.

After everything worked, I've felt a bit itchy since I've been thinking a long time ago to implement stream compression, so I've added CompressedNetworkStream, but then I needed an efficient FIFO for byte arrays, so I had to implement a circular MemoryBuffer.

As you can see, from a simple SslStream demo, it became a little bit more. I had fun while doing it, but it left little time for testing, so if you'd like it to be more than a demo code, you'll have to do it yourself, let me know if you find bugs!

As always, you can find the project at github:
https://github.com/drorgl/ForBlog/tree/master/SslStreamChat


No comments:

Post a Comment