1

I'm quite stuck trying to perform a POST request using a P12 certificate that was provided by the server. I've never dealt with HTTPS before, and I'm going in circles (I'm not sure I'm even using the right terminology). I know this must be quite basic, but this is the first time I need to code something like this.

I've even tried to replicate what others have done for exactly the same purpose, but for some reason it does not work (perhaps it has to do with how it works in Android, I'm not sure).

This is what I have right now:

// P12 certificate is placed in "assets" folder
AssetManager assets = Application.Context.Assets;
byte[] bytes;

using (StreamReader sr2 = new StreamReader(assets.Open("myCertificate.p12")))
{
    using (var memstream = new MemoryStream())
    {
        sr2.BaseStream.CopyTo(memstream);
        bytes = memstream.ToArray();
    }
}

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.aidap.naimes.faa.gov/aidap/XmlNotamServlet");

X509Certificate2 clientCertificate = new X509Certificate2(bytes, "myPassword");

req.ClientCertificates.Add(clientCertificate);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";

string postData = "uid=myUsername&password=myPassword&active=Y";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
req.ContentLength = byteArray.Length;

// **Next line triggers the Exception**
using (Stream dataStream = req.GetRequestStream())
{
    dataStream.Write(byteArray, 0, byteArray.Length);
    dataStream.Close();
}

// Show the first 10 lines
using (StreamReader sr = new StreamReader(req.GetResponse().GetResponseStream()))
{
    for (int i = 0; i < 10; i++)
        Console.WriteLine(sr.ReadLine());
}

When calling GetRequestStream() I get the following (I copy the first bit, as it's quite long):

{System.Net.WebException: Error: SecureChannelFailure (One or more errors occurred.) ---> System.AggregateException: One or more errors occurred. ---> System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> Mono.Btls.MonoBtlsException: Syscall at Mono.Btls.MonoBtlsContext.ProcessHandshake () [0x00038] in <9624f2cab6ac4ffc9c31e9469d40591a>:0 at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake

The certificate and password seems to work correctly, as I can inspect in debug mode and verify that all details are loaded in "clientCertificate".

EDIT

So I tried following Ketan's suggestion but I'm not quite sure how to add a trace to an Android project. What I did, is to create a small console application but I didn't have to add a trace because it worked perfectly right away.

I also tried a different approach with RestSharp and it worked once again perfectly in the console application but not in Xamarin:

var client = new RestClient("https://www.aidap.naimes.faa.gov/aidap/XmlNotamServlet");
client.ClientCertificates = new X509CertificateCollection() { clientCertificate };

string postData = "uid=myUsername&password=myPassword&active=Y";

var request = new RestRequest(Method.POST);
request.AddParameter("application/x-www-form-urlencoded", postData, ParameterType.RequestBody);

var response = client.Execute(request);

So there must be something preventing the SSL from working in Android.

Manu
  • 141
  • 2
  • 13
  • 1
    You can add trace in the config to find root cause of the issue. Refer to this: https://stackoverflow.com/questions/5977817/debugging-failing-https-webrequest – Ketan Apr 16 '18 at 02:35
  • I found this other SO question about similar error, not sure it is directly related but you can check it out. https://stackoverflow.com/a/3949827/3380336 – Ketan Apr 16 '18 at 02:39
  • Thank you Ketan. I tried with a console application and it worked perfectly (I was going to add the trace in there, but finally I did not have to). Any advice on how to do the same in Xamarin Android? – Manu Apr 28 '18 at 21:47

0 Answers0