Storing a .p12 certificate in a keychain for later use

I am trying to keep an eye on apple docs for working with p12 client certificates here:

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

I successfully downloaded the .p12 certificate from the file system:

- (SecIdentityRef)getClientCertificate:(NSString *) certificatePath { SecIdentityRef identity = nil; NSData *PKCS12Data = [NSData dataWithContentsOfFile:certificatePath]; CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; CFStringRef password = CFSTR("password"); const void *keys[] = { kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items); CFRelease(options); CFRelease(password); if (securityError == errSecSuccess) { NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items)); CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); identity = (SecIdentityRef) CFDictionaryGetValue(identityDict, kSecImportItemIdentity); } else { NSLog(@"Error opening Certificate."); } return identity; } 

Then I get a certificate for this identity:

 - (CFArrayRef)getCertificate:(SecIdentityRef) identity { SecCertificateRef certificate = nil; SecIdentityCopyCertificate(identity, &certificate); SecCertificateRef certs[1] = { certificate }; CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL); SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); SecTrustRef myTrust; OSStatus status = SecTrustCreateWithCertificates(array, myPolicy, &myTrust); if (status == noErr) { NSLog(@"No Err creating certificate"); } else { NSLog(@"Possible Err Creating certificate"); } return array; } 

But what I really want to do is store the certificate (or identifier) ​​in my application key chain, so I do not read it from the file system.

A few questions:

  • What should i store? Certificate or identity?
  • How to save and receive it?

The link above talks about how to "get and use permalinks to keychains" really confuses me.

It also talks about “searching for a certificate in keychains,” but it mentions the name of the certificate to find it. I'm not sure where the "name" comes from.

+3
source share
2 answers

I can’t think of a good reason to keep the certificate in the keychain, although I’m sure there may be some. I only store the identifier (which is the private key) in the keychain. To simplify the search for identity in the key chain, you create a permalink to it (see List 2-3 in the link), and then save this permalink in the file system for your application. A persistent ref is just a CFDataRef, which you can use to freely access an NSData object and then easily save / load. If you need a secret key for crypto / independently, you use this permalink to download the identifier from the keychain (see Listing 2-4 in the link). I would publish the code for you, but now I am rebuilding my development machine and Xcode has not yet been installed.

+2
source
  1. What should i store? Certificate or identity?

It depends on what you are doing and whether you need a secret key on your device for authentication. SecIdentityRef contains the certificate and private key. If you use the .p12 file for authentication, then most likely you will want to save and use full authentication. If you only need a certificate, I would not download the full .p12 to disk, since it contains a private key.

  1. How do I save and receive it?

I would recommend storing your identity (or certificate) in kSecAttrLabel keys and use kSecAttrLabel as a unique reference for requests.

The documentation that you need to pay attention to is Identity Storage in the Keychain , which directs you to the Storage of the Certificate in the Keychain and outlines some minor differences required between storing the identity and certificate.

This is done as follows (adapted from the links above):

Save to Keychain

 // Create a query (with unique label for reference later) NSDictionary* addquery = @{ (id)kSecValueRef: (__bridge id)identity, (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrLabel: @"My Identity", }; // Add the identity to the keychain OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addquery, NULL); if (status != errSecSuccess) { // Handle the error } 

Download from keychain

 // Query the keychain for your identity NSDictionary *getquery = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrLabel: @"My Identity", (id)kSecReturnRef: @YES, }; // Retrieve the identity from the keychain SecIdentityRef identity = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)getquery, (CFTypeRef *)&identity); if (status != errSecSuccess) { <# Handle error #> } else { <# Use identity #> } if (identity) { CFRelease(identity); } // After you are done with it 

As mentioned in RyanR, you can also create a permalink to a keychain item after you save it, and then save it to a file. I would recommend adding [kSecReturnPersistentRef][3] to your addquery to achieve this.

0
source

All Articles