Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a X509 Certificate in .Net Compact Framework for Client Authentication HTTPRequest

I'm working in Windows Mobile 6 and would like to have client authentication when talking to a Apache webserver. I have a certificate in my local certificate store and it should be rather straightforward:

X509Store myStore = new X509Store("MY", StoreLocation.CurrentUser);
myStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = myStore.Certificates;
X509Certificate2 clientcertificate;
foreach (X509Certificate 2certificate in certificates) {
     clientcertificate = certificate; //omitted code to validate certificate
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(webPage);
req.AllowWriteStreamBuffering = true;
req.AllowAutoRedirect = false;
req.Method = "POST";
req.ContentType = "text/xml";
req.Accept = "text/xml";
req.ClientCertificates.Add(clientcertificate);
Stream stream = req.GetRequestStream();
stream.Write(buffer, 0, buffer.Length);
stream.Close();

This code segment works as long as I remove the "req.ClientCertificates.Add(clientcertificate)" line.

Once that's inserted, I get a "Could not establish secure channel for SSL/TLS". Maddeningly enough, when I use this exact code in the regular .Net Framework it transmits the certificate perfectly.

Does anyone know if this is possible in Compact Framework? If I can't present the X509Certificate for Client Authentication, what other ways should I pursue to ensure that authentication is proper (I should have access to CAPI or other Microsoft Cryptographic modules)

Thanks.

like image 664
Michael Fan Avatar asked Dec 11 '12 21:12

Michael Fan


2 Answers

It could be that your Apache Server does not support secure connections.

For example, I've got a few websites on hosted domains that cost little or nothing. I use these websites to test code on all the time.

But, to get SSL capabilities, I've got to shell out like $50/month. So, I can't test those on my sites.

To test: If the Apache Server supports SSL, you should be able to replace the URL with the SSL equivalent: http://www.stackoverflow.com with https://www.stackoverflow.com

like image 68
jp2code Avatar answered Oct 18 '22 16:10

jp2code


Good news: I solved it. It turned out not to have to do with the .Net Compact Framework. In 3.5 CF, HTTPWebRequest.ClientCertificates is supported as long as the X509 certificate can be accessed.

The reason why the SSL Handshake failed was because of a trust issue with the server side certificate. Our server certificates were self-signed and we used certificates that were signed for the wrong URL, so the application rightly wouldn't trust the provided server certificate. For testing purposes, we put in place a Trust All Certificates policy, which will be removed for the production.

sealed class AcceptAllCertificatePolicy : ICertificatePolicy
{
    private const uint CERT_E_UNTRUSTEDROOT = 0x800B0109;

    public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate
    certificate, WebRequest request, int certificateProblem)
    {
        // Just accept.
        return true;
    }
    /*public bool CheckValidationResult(ServicePoint sp,
    X509Certificate cert, WebRequest req, int problem)
    {
        return true;  
    }*/
}

Referenced right before the HTTPWebRequest

System.Net.ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();

And this solves our problem with the SSL/TLS secure channel.

like image 25
Michael Fan Avatar answered Oct 18 '22 15:10

Michael Fan