Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...


Raw envies

So I wanted to blog, again, about client certificates. The original motivation was that Mono 1.1.9 added support for them inside XSP. This means it's now possible to use the HttpClientCertificate class to get the identity of the user. Client certificates are a nice way to authenticate users without having to maintain a database - just drop, for a fee, the problem to the certificate issuer. Actually it isn't as easy as it sound but, mostly, not for technological reasons ;-).

<%@ Page language="c#" %> <html> <head> <script runat="server"> void Page_Load (object sender, EventArgs e) { string user = "World"; HttpClientCertificate hcc = Request.ClientCertificate; if (hcc.IsPresent) { System.Security.Cryptography.X509Certificates.X509Certificate cert = new System.Security.Cryptography.X509Certificates.X509Certificate (hcc.Certificate); user = cert.GetName (); } info.Text = String.Format ("Hello {0}!", user); } </script> </head> <body> <form runat="server"> <asp:Label id="info" runat="server" /> </form> </body> </html>

This ASP.NET sample will print Hello World! for anyone without a client certificate and Hello something! if you have a client certificate. A bit more detailled sample is available in SVN.

However this original blog got interrupted by a question about making client certificate works on the MS runtime. You see there's a little black magic going on there because the framework isn't exposing the certificate stores at all (at least not before 2.0). So you end up, source wise, supplying a certificate without a private key, which doesn't (or shouldn't) make sense to the readers.

using System; using System.IO; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; class Program : ICertificatePolicy { public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error) { if (error != 0) Console.WriteLine ("Untrusted server certificate"); // whatever the reason we do not stop the SSL connection return true; } static void Main (string[] args) { ServicePointManager.CertificatePolicy = new Program (); HttpWebRequest req = (HttpWebRequest) WebRequest.Create (args [0]); req.ClientCertificates.Add ( X509Certificate.CreateFromCertFile (@"c:\poupou.cer")); WebResponse resp = req.GetResponse (); StreamReader sr = new StreamReader (resp.GetResponseStream ()); Console.WriteLine (sr.ReadToEnd ()); } }

This works because, behind the scene, the same certificate is searched in the user's store and finally, if you're lucky, a private key associated to the certificate will be found and used to prove your identity to the server. Lesson: You need to be extra careful when importing the PKCS#12 file in Windows. Not cute

Because of the trouble of using MS runtime, and also my reluctance to use IE when browsing a site not ending with *.microsoft.com, I never tried using client certificates with them. Well that was a mistake :-(. Turns out that our current code (1.1.9) delays the hashing of the handshake data at the end of each handshake message. This isn't a problem unless (a) several message are concatened in a single handshake message and (b) we need to use the hash value between two of those messages. Guess what ? this is exactly what both IE and MS's HttpWebRequest (sharing deep down the same code) does when using client certificates - but not when using wget/OpenSSL.

I fixed that, actually I have a few more tests to run before committing this to SVN, so I guess, and hope, this will bring closure to this feature as there's so much more to do...

Huh... so what about raw envies ? I was looking for a name for the ASN.1 Viewer and this turned out to be an acronym for it. Nice but maybe someone got a better idea ???

9/29/2005 22:26:17 | Comments | Permalink

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.