IPhone app with SSL client certs

2019-03-08 02:18发布

问题:

I'm building an iphone app that needs to access a web service over https using client certificates. If I put the client cert (in pkcs12 format) in the app bundle, I'm able to load it into the app and make the https call (largely thanks to stackoverflow.com).

However, I need a way to distribute the app without any certs and leave it to the user to provide his own certificate. I thought I would just do that by instructing the user to import the certificate in iphone's profiles (settings->general->profiles), which is what you get by opening a .p12 file in Mail.app and then I would access that item in my app. I would expect that the certificates in profiles are available through the keychain API, but I guess I'm wrong on that.

1) Is there a way to access a certificate that I've already loaded in iphone's profile in my app?

2) What other options I have for loading a user specified certificate in my app? The only thing I can come up with is providing some interface where the user can give an URL to his .p12 cerificate, which I can then load into the app's keychain for later use, but thats not exactly user-friednly. I'm looking for something that would allow the user to put the cert on phone (email it to himself) and then load it in my app.

回答1:

I've tried with this:

NSString *thePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"p12"]; 
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; 
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data; 
CFStringRef password = CFSTR("pass"); 
const void *keys[] = { kSecImportExportPassphrase }; 
const void *values[] = { password }; 
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 
SecPKCS12Import(inPKCS12Data, optionsDictionary, &items); 

inPKCS12Data is correct but items is empty. What is happening?



回答2:

I've done this for a recent app by making the documents folder for the app accessible via itunes. Our users are then instructed to drag their generated key (in a p12 format file) into the documents panel for our app in iTunes. When the app is started, it checks for the existence of the p12 file and, if it exists, imports the file into the keychain.

It's not the simplest procedure, but it is the most secure because you don't have a private key file being sent around via email.



回答3:

If a .p12 file isn't too big you could encode it using Base64 and then embed a link in an email with a custom url scheme, e.g.:

myapp://certificate/<base 64 data>

User clicks the link, your app saves the certificate somewhere for future use. Just make sure that Mail.app on the iPhone won't mangle the email.



回答4:

Apple does restrict the use of device-wide keys/certificates to it's own applications/services, such as WiFi, VPN, Mail, etc. Third-party applications are not able to use any of these keys/certs (without jailbreaking). However, applications are able to import, store, and use keys and certificates in a in-app keychain. In addition, you can share keys/certs across multiple applications with the keychain-access-group feature in iOS.

I recently published a blog post titled In-App Mobile Certificates Made Easy with mCMS, which may have helped you out. Our company is developing an API that makes it easy to support in-app certificates, obtained directly from your Microsoft-based PKI. Our solution also offers on-device key generation, instead of generating a P12 on another machine and trying to import it into your app.



回答5:

If you're using AirWatch for app distribution, their SDK provides the ability to provision certificates from your Certificate Authority to your registered devices. This allows you to provision your certs, and then access them from your app's code.



回答6:

Does the code suggested in Finding a Certificate In the Keychain work for you?



回答7:

Oh man, this brings up painful memories from October/November 2009. I was able to successfully get client-side certs to work but I had to port libcurl to the iPhone (which wasn't easy since the NDA was still in effect at the time).

I haven't done iPhone app development in over a year so I don't know how much is changed, but if I were you I'd first try to get by without client-side certs and if you absolutely must have them you can use libcurl with PEM formatted certs.