Estoy intentando usar certificates de cliente para una connection SSL usando MonoTouch. Parece que hay varios ejemplos para hacer esto usando objective-c, y la solución que estoy buscando probablemente sea similar a la que se respondió aquí, pero en MonoTouch (C #).
Estoy usando la class NSUrlConnection en MonoTouch, y he anulado la class NSUrlConnectionDelegate para responder al desafío de authentication.
Pude cargar los certificates del file, pero no he podido encontrar una representación útil de los certificates para responder al desafío de authentication.
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 NSUrlCnetworkingential cnetworking = new NSUrlCnetworkingential(secTrustRef, true); challenge.Sender.UseCnetworkingentials(cnetworking, challenge); } }
Algunas notas:
No tengo un entorno de server configurado para probar esto, pero testing esto:
Reemplazar:
... MonoTouch.Security.SecTrust trust = (MonoTouch.Security.SecTrust)items[0]["trust"]; IntPtr secTrustRef = trust ...
con:
... NSObject obj = items[0]["trust"]; IntPtr secTrustRef = obj.Handle; ... create and use your cnetworkingentials GC.KeepAlive (obj); // just in case ;-) ...
Utilice HttpWebRequest. En el punto 2 de las notas de la pregunta dije que la propiedad HttpWebRequest.ClientCertificates arroja una exception no implementada y, por lo tanto, descarté esta opción. Lo hace si intenta configurar la propiedad con una nueva colección, pero si solo utiliza Get accessor, puede agregar un certificate de cliente a la colección.
Como nota al margen, el uso de HttpWebRequest hace que la aplicación sea más transportable a otros dispositivos, parte de la razón por la que estamos usando MonoDevelop, así que ganar-ganar.