5

I am attempting to use client certificates for an SSL connection using MonoTouch. There seems to be several examples to do this using objective-c, and the solution I am looking for would probably be similar the one answered here but in MonoTouch (C#).

I am using the NSUrlConnection class in MonoTouch, and have overridden the NSUrlConnectionDelegate class to respond to the authentication challenge.

I have been able to load the certificates from file, but I have been unable to find a useful representation of the certificates to respond to the authentication challenge.

public override void ReceivedAuthenticationChallenge(NSUrlConnection connection, NSUrlAuthenticationChallenge challenge)
{
   if (string.Equals(challenge.ProtectionSpace.AuthenticationMethod, "NSURLAuthenticationMethodClientCertificate", StringComparison.OrdinalIgnoreCase)) {
      string password = "<password_signed_certificate>";
      byte[] data = File.ReadAllBytes("<path_of_file_in_ios_sandboxed_filesystem_pkcs>");
      NSDictionary opt = NSDictionary.FromObjectsAndKeys(new object[]{password}, new object[]{"passphrase"});
      NSDictionary[] items;
      SecStatusCode stat = SecImportExport.ImportPkcs12(data, opt, out items); // Uses MonoTouch.Security namespace
      MonoTouch.Security.SecTrust trust = (MonoTouch.Security.SecTrust)items[0]["trust"];
      // Everything to this point works, and I can inspect the trust object that all the expected certificate properties (IssuerName etc.) are correct

      IntPtr secTrustRef = trust // ????? How do I bridge this gap
      // NSUrlConnection does not utilise MonoTouch security namespace

      NSUrlCredential cred = new NSUrlCredential(secTrustRef, true);
      challenge.Sender.UseCredentials(cred, challenge);
   }
}

Some notes:

  1. I have seen the objective-c solutions but I have not found the equivalent set of steps required in MonoTouch (C#).
  2. I cannot utilise HttpWebRequest, as the monotouch implementation of httpWebRequest.ClientCertificates (a collection) throws a 'not implemented exception'.
  3. I have also attempted to use the Mono.Security.X509 and System.Security.Cryptography.X509Certificates namespaces to open the certificates with success, but again I cannot utilise the class instances to respond to the Authentication challenge, as I need to create a NSUrlCredential object which only accepts an IntPtr.
  4. See also this.
Community
  • 1
  • 1
Bruce
  • 63
  • 5

2 Answers2

2

I don't have a server environment set up to try this, but try this:

Replace:

...
MonoTouch.Security.SecTrust trust = (MonoTouch.Security.SecTrust)items[0]["trust"];
IntPtr secTrustRef = trust
...

with:

...
NSObject obj = items[0]["trust"];
IntPtr secTrustRef = obj.Handle;
... create and use your credentials
GC.KeepAlive (obj); // just in case ;-)
...
poupou
  • 43,413
  • 6
  • 77
  • 174
  • Thanks :) That got me past the issue of how to get the handle, and hence the 'accepted answer'. Unfortunately the request still fails, (even though installing certificate as part of a profile on iPhone works using Safari connected to the site). I have not seen anyone have success using MonoTouch and client certificates. Just hoping I am doing something stupid, and not that it is simply not possible / not supported. Will keep researching. Appreciate the assistance. – Bruce Oct 15 '12 at 02:34
1

Use HttpWebRequest. In the question notes point 2 I said the HttpWebRequest.ClientCertificates property throws a not implemented exception, and I therefore ruled out this option. It does if you try to set it the property with a new collection, but if you just use the Get accessor, you can add a client certificate to the collection.

As a side note, using HttpWebRequest makes the app more transportable to other devices, part of the reason we are using MonoDevelop so win-win.

Bruce
  • 63
  • 5