I have been working on this problem for the last couple of days and I am not getting anywhere.
The scenario is:
An iOS app in the field will call my REST Service (.NET). My REST service will call the Apache web service using the Mutual SSL handshake. Whatever data I receive I have to pass back to iOS devices in the field.
The only issue is the 2nd part of communication between My REST Service and Apache Web service.
Client Certificates have been signed using the key usages of Client authentication, Digital Certificate, Key Encipherment. The root signers of my certificate have been placed on the Apache server. If we try using the Web browser we can perform the handshake without any issues.
Sample code which I am using to perform the authentication using SslStream. Using this method I get an error stating
The message received was unexpected or badly formatted
and the guys who manage the Apache web server say that they can see the request coming in, but according to them they are not receiving a certificate with this.
var certificate = @“certificate.cer”;
var hostAddress = “hostAddress";
var certificates = new X509Certificate2Collection(new X509Certificate2(certificate));
RunClient(hostAddress, 1316, certificates);
static void RunClient(string hostName, int port, X509Certificate2Collection certificates)
{
TcpClient client = new TcpClient(hostName, port);
SslStream sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate);
try
{
sslStream.AuthenticateAsClient(hostName, certificates, SslProtocols.Ssl3, true);
Write("authenticated.");
}
catch (AuthenticationException ex)
{
Write("Inner: " + ex.InnerException.Message);
}
catch (Exception ex)
{
Write(ex.Message);
}
}
Sample code which I am using to perform the authentication using HttpWebRequest. Using this method gives me the following issue
The request was aborted: Could not create SSL/TLS secure channel.
var certificate = @“certificate.cer”;
var hostAddress = “hostAddress";
var certificates = new X509Certificate2Collection(new X509Certificate2(certificate));
public static T Post(string url, string body, X509Certificate2 cert)
{
var webRequest = FBJsonRequestService.CreateRequest(url, cert, WebRequestMethods.Http.Post, body);
using (var webResponse = webRequest.GetResponse())
{
return CreateResponse(webResponse);
}
}
var webRequest = (HttpWebRequest) WebRequest.Create(url);
webRequest.ClientCertificates.Add(cert);
//webRequest.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
webRequest.Method = method;
webRequest.ContentType = "application/json; charset=utf-8";
if (body != null)
{
using (var streamWriter = new StreamWriter(webRequest.GetRequestStream()))
{
streamWriter.Write(body);
}
}
return webRequest;
I hope this makes sense. All I want to know is if whatever I am doing is right or I am doing it wrong.
I think the content of file certificate.cer is incorrect. Extension .cer in my opinion contains only certificate but not private key.
You have to use certificate.p12 or certificate.pfx that contains also private key. These extensions represent PKCS#12 standard. There can also be whole certificate chain included in these files.
You can load a p12 file using different constructor of X509Certificate2 class. Please look at this documentation.
Thanks Pepo,
I figured this out that I was using the wrong file. I had to use the PFX file instead of CER. My issue turned out to be something else altogether. It was some security restriction of Certificate itself. Before posting this I wasn't even sure that whether I was doing the right thing.
I have created the following blog for someone in future needs any help regarding this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With