将客户端证书导入iPhone的钥匙串

时间:2011-12-01 10:05:27

标签: iphone ios xcode client-certificates pkcs#12

我正在编写一个与服务器通信的应用程序,该服务器要求客户端使用客户端证书对自身进行身份验证。我需要从应用程序包中的.p12文件中提取证书,并将其添加到应用程序密钥链中。

我一直试图弄清楚如何让它从Apple的"Certificate, Key, and Trust Services Tasks for iOS"开始工作,但对我而言似乎不完整,并没有说明我如何在钥匙串中添加任何东西(?)。

我很失落,任何帮助都是适当的,提前谢谢!

1 个答案:

答案 0 :(得分:5)

Certificate, Key, and Trust Services Tasks for iOS”确实包含从.p12文件中提取证书的足够信息。

    清单2-1中的
  • 演示了如何提取 SecIdentityRef

  • 清单2-2第二行(// 1)中的
  • 显示了如何复制 SecIdentityRef中的 SecCertificateRef

示例加载p12文件,解压缩证书,安装到钥匙串。 (不包括错误处理和内存管理)

  NSString * password = @"Your-P12-File-Password";
  NSString * path = [[NSBundle mainBundle]
                     pathForResource:@"Your-P12-File" ofType:@"p12"];

  // prepare password
  CFStringRef cfPassword = CFStringCreateWithCString(NULL,
                                                     password.UTF8String,
                                                     kCFStringEncodingUTF8);
  const void *keys[]   = { kSecImportExportPassphrase };
  const void *values[] = { cfPassword };
  CFDictionaryRef optionsDictionary
  = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1,
                                                  NULL, NULL);

  // prepare p12 file content
  NSData * fileContent = [[NSData alloc] initWithContentsOfFile:path];
  CFDataRef cfDataOfFileContent = (__bridge CFDataRef)fileContent;

  // extract p12 file content into items (array)
  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
  OSStatus status = errSecSuccess;
  status = SecPKCS12Import(cfDataOfFileContent,
                           optionsDictionary,
                           &items);
  // TODO: error handling on status

  // extract identity
  CFDictionaryRef yourIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
  const void *tempIdentity = NULL;
  tempIdentity = CFDictionaryGetValue(yourIdentityAndTrust,
                                      kSecImportItemIdentity);

  SecIdentityRef yourIdentity = (SecIdentityRef)tempIdentity;


  // get certificate from identity
  SecCertificateRef yourCertificate = NULL;
  status = SecIdentityCopyCertificate(yourIdentity, &yourCertificate);


  // at last, install certificate into keychain
  const void *keys2[]   = {    kSecValueRef,             kSecClass };
  const void *values2[] = { yourCertificate,  kSecClassCertificate };
  CFDictionaryRef dict
  = CFDictionaryCreate(kCFAllocatorDefault, keys2, values2,
                                            2, NULL, NULL);
  status = SecItemAdd(dict, NULL);

  // TODO: error handling on status