Custom Certificate in iOS App

2019-06-10 19:35发布

问题:

I created a certificate (of p12 type) that I installed onto an iPad using Apple Configurator. I now want to access that certificate in an app I've written but I can't seem to find a source example for it. There are lots of examples on how to use certificates but I've been unable to find anything on how to import it into an app.

Can someone point me in the right direction? Thanks in advance.

* NEW *

So I tried following the tutorial here https://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-SW13 using Listing 2-1 and Listing 2-2. For now I gave up on getting the certificate from the keychain and instead I load it from the main Bundle.

NSData *certData = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"myfile.com" ofType:@"pfx"]];
CFDataRef myCertData = (__bridge_retained CFDataRef)(certData); 

I'm not certain whether my loading is correct but when I debug certData is not NULL and contains bytes.

Next I modified the code in the two listings since the method signatures don't really match an Objective C method signature. Someone help me out here why Apple would show it this way? No code inside the function was modified.

- (OSStatus) extractIdentityAndTrust: (CFDataRef) inPKCS12Data withIdentity:(SecIdentityRef *) outIdentity withTrust:(SecTrustRef *) outTrust withPassword:(CFStringRef) keyPassword
{
    OSStatus securityError = errSecSuccess;
    const void *keys[] =   { kSecImportExportPassphrase };
    const void *values[] = { keyPassword };
    CFDictionaryRef optionsDictionary = NULL;

    optionsDictionary = CFDictionaryCreate(NULL, keys, values, (keyPassword ? 1 : 0), NULL, NULL);

    CFArrayRef items = NULL;
    securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);

    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust,
                                             kSecImportItemIdentity);
        CFRetain(tempIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);

        CFRetain(tempTrust);
        *outTrust = (SecTrustRef)tempTrust;
    }

    if (optionsDictionary)
        CFRelease(optionsDictionary);

    if (items)
        CFRelease(items);

    return securityError;
}

Next I modified the method signature for copySummaryString. I also had to add a deference inside the function for the 'identity' variable.

- (NSString *)copySummaryString:(SecIdentityRef *) identity
{
    // Get the certificate from the identity.
    SecCertificateRef myReturnedCertificate = NULL;
    OSStatus status = SecIdentityCopyCertificate (*identity, &myReturnedCertificate);

    if (status) {
        NSLog(@"SecIdentityCopyCertificate failed.\n");
        return NULL;
    }

    CFStringRef certSummary = SecCertificateCopySubjectSummary
    (myReturnedCertificate);

    NSString* summaryString = [[NSString alloc] initWithString:(__bridge NSString *)certSummary];

    CFRelease(certSummary);

    return summaryString;
}

Finally in my calling function I created a identity and trust variable that I pass around:

[self extractIdentityAndTrust:myCertData withIdentity:identity withTrust:trust withPassword:CFSTR("supersecret")];
[self copySummaryString:identity];

When I try to run this I get a Thread 1: EXC_BAD_ACCESS(code=1, adress=0x2b) error and XCode pauses on the following line:

CFStringRef certSummary = SecCertificateCopySubjectSummary

This code doesn't reference any variable I created so I'm really surprised it's crashing here. The ultimate goal with loading this certificate is to use it for HTTPS. I hope that I'm at least on the right path here.

回答1:

Here is the documentation and example about finding and using of a pre-installed certificate and identity through your mobile app.

https://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-DontLinkElementID_10

*NEW

I checked your update. Both you methods works like charm.

I used below source to call your methods, and was able to extract the SummaryString properly.

SecIdentityRef identity = nil;
SecTrustRef trust = nil;

NSData *certData = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"[Dev] InHouse_Certificates" ofType:@"p12"]];
CFDataRef myCertData = (__bridge_retained CFDataRef)(certData);

[self extractIdentityAndTrust:myCertData withIdentity:&identity withTrust:&trust withPassword:CFSTR("1234")];
NSString* summaryString = [self copySummaryString:&identity];