I need to connect to a secure API which requires a certificate be attached to the request. I have installed the needed certificate on my device (its keychain), and I’ve just had a world of trouble trying to get it to work. Ideally I’d like to use ASIHTTPRequest to accomplish this, since it has the convenient setClientCertificateIdentity: method. However, I just can’t get the installed cert into the needed file format (SecIdentityRef).
I have tried code from Apple’s documentation to extract the Cert from the keychain, which doesn’t seem to work (just falls into the error). I have even tried, just for the heck of it, embedding the cert into the application itself to see at least if I can get THAT working, but no dice. I convert it to NSData, per all the stack-overflow threads I’m reading, but then when I attempt to use various methods for extracting the SecIdentityRef from the data, it always just fails.
I have also tried to do it without ASIHTTPRequest, and just to utilize the didReceiveAuthenticationChallenge method, but I ran into a roadblock there as well. That being said, I DID have success in having the code find my cert I want via the following code:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
SecTrustEvaluate(trustRef, NULL);
CFIndex count = SecTrustGetCertificateCount(trustRef);
for (CFIndex i = 0; i < count; i++)
{
SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, i);
CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef);
CFDataRef certData = SecCertificateCopyData(certRef);
NSLog(@"certSummary: %@", certSummary);
}
This did print the Cert I need. But after that, it’s a matter of sending it back to the server I guess, which didn’t seem to work with the code I had at hand. I just still got no response and no data back.
So ideally, to sum up, I’d ideally like to use ASIHTTPRequest (despite that I understand it’s no longer supported), and I need the Cert in SecIdentityRef format in order to attach to the request for sending. Seems simple enough, I know. Now I’m concerned as to whether this is even possible?
Really would appreciate any clear direction on this. Thanks in advance!
-Vincent
To answer my own question, or at least provide more info – Turns out this may not be possible, at least part of it. The iOS request requires you to go through the authentication method “didReceiveAuthenticationChallenge” to send the cert, but if you have an API that requires the cert to be attached to the request, there is absolutely no way to get it from the keychain up front.. At least from what I’m gathering.
The only way to accomplish it is to have access to the actual cert up front, rather than just pulling it from the keychain. This can be done by either embedding it into the app, or possibly downloading it from a source. From there, the cert can be formatted to be attached to the request. However, I still have yet to get this piece working, even when embedding the cert in the app. The conversion from NSData to SecIdentityRef still has me lost, and no code seems to work to do that conversion. Any assistance on that would be greatly appreciated!