public static SecIdentity Import(byte[] data, string password, ImportOptions options = null) { if (data == null) { throw new ArgumentNullException("data"); } if (string.IsNullOrEmpty(password)) // SecPKCS12Import() doesn't allow empty passwords. { throw new ArgumentException("password"); } using (var pwstring = CFString.Create(password)) using (var optionDict = CreateImportOptions(pwstring, options)) { CFDictionary [] array; SecStatusCode result = SecImportExport.ImportPkcs12(data, optionDict, out array); if (result != SecStatusCode.Success) { throw new InvalidOperationException(result.ToString()); } return(new SecIdentity(array [0].GetValue(ImportItemIdentity.Handle))); } }
public static SecIdentity GetIdentity(X509Certificate certificate) { /* * If we got an 'X509Certificate2', then we require it to have a private key * and import it. */ var certificate2 = certificate as X509Certificate2; if (certificate2 != null) #if MONOTOUCH { return(SecIdentity.Import(certificate2)); } #else { return(SecImportExport.ItemImport(certificate2)); } #endif /* * Reading Certificates from the Mac Keychain * ========================================== * * Reading the private key from the keychain is a new feature introduced with * AppleTls on XamMac and iOS. On Desktop Mono, this new feature has several * known issues and it also did not received any testing yet. We go back to the old * way of doing things, which is to explicitly provide an X509Certificate2 with a * private key. * * Keychain Dialog Popups * ====================== * * When using Xamarin.Mac or Xamarin.iOS, we try to search the keychain * for the certificate and private key. * * On Xamarin.iOS, this is easy because each app has its own keychain. * * On Xamarin.Mac, the .app package needs to be trusted via code-sign * to get permission to access the user's keychain. [FIXME: I still have to * research how to actually do that.] Without this, you will get a popup * message each time, asking you whether you want to allow the app to access * the keychain, but you can make these go away by selecting "Trust always". * * On Desktop Mono, this is problematic because selecting "Trust always" * give the 'mono' binary (and thus everything you'll ever run with Mono) * permission to retrieve the private key from the keychain. * * This code would also trigger constant keychain popup messages, * which could only be suppressed by granting full trust. It also makes it * impossible to run Mono in headless mode. * * SecIdentityCreate * ================= * * To avoid these problems, we are currently using an undocumented API * called SecIdentityRef() to avoid using the Mac keychain whenever a * X509Certificate2 with a private key is used. * * On iOS and XamMac, you can still provide the X509Certificate without * a private key - in this case, a keychain search will be performed (and you * may get a popup message on XamMac). */ #if MOBILE using (var secCert = new SecCertificate(certificate)) { return(SecKeyChain.FindIdentity(secCert, true)); } #else return(null); #endif }