如何以编程方式将证书导入我的iOS应用程序的钥匙串,并在需要时将身份传递给服务器?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何以编程方式将证书导入我的iOS应用程序的钥匙串,并在需要时将身份传递给服务器?相关的知识,希望对你有一定的参考价值。
我正在开发一个ios5应用程序,它将促进两个用户之间的移动支付。作为付款流程的一部分,发件人和收件人需要与服务器通信。服务器要求双方在连接时启动身份验证质询时显示其身份。
目前,我在代码中使用以下两种方法对证书过程进行了硬编码:
NSURLConnection委托didReceiveAuthenticationChallenge
(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge
{
NSLog(@"Authentication challenge");
// Load Certificate
NSString *path = [[NSBundle mainBundle] pathForResource:@"PKCS12" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);
SecCertificateRef myCertificate;
SecIdentityCopyCertificate(myIdentity, &myCertificate);
const void *certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
C方法extractIdentityAndTrust
OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
OSStatus securityError = errSecSuccess;
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);
securityError = SecPKCS12Import(inP12data, options, &items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
*trust = (SecTrustRef)tempTrust;
}
if (options) {
CFRelease(options);
}
return securityError;
}
我已多次测试此代码并取得了成功。现在我试图继续并允许存储适当的身份,然后从应用程序的钥匙串中检索。我的目标是允许用户通过iTunes文件共享或Dropbox导入他们的P12文件并将其保存到钥匙串。
我查看了Apple的Getting and Using Persistent Keychain References文档,并且无法弄清楚如何导入身份。他们的代码对我来说有点混乱,因为他们使用未声明的变量/引用(特别是
&persistent_ref
变量)。如果有人可以帮助破译它,那将非常感激。
TL; DR:如何将P12文件的内容保存到我的iOS 5应用程序钥匙串中,稍后将其检索到NSURLConnection didReceiveAuthenticationChallenge方法?
以下代码应该可以解决问题:
NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];
[secIdentityParams setObject:(id)myIdentity forKey:(id)kSecValueRef];
OSStatus status = SecItemAdd((CFDictionaryRef) secIdentityParams, NULL);
您可以通过传递要查找或创建的键值对字典来与Keychain进行交互。每个键代表一个搜索选项或钥匙串中项目的属性。键是预定义的常量,必须根据要存储的数据类型使用。这些密钥可以在Apple的开发人员文档中找到。
我认为Apple的源代码确实缺少persistentRef的分配。他们应该在方法的开头添加这样的声明:
NSData *persistentRef = nil;
请注意,使用持久性引用不是强制性的。上面的代码应该可以正常工作。正如Apple解释得好:
因为持久引用在程序调用之间保持有效并且可以存储在磁盘上,所以您可以使用一个来更容易地找到您需要重复使用的Keychain项目
Swift 4.0
if let url = Bundle.main.url(forResource: "XXX", withExtension: "pem") {
let PKCS12Data = NSData(contentsOf: url)
let inPKCS12Data = CFDataCreate(kCFAllocatorDefault, PKCS12Data!.bytes.assumingMemoryBound(to: UInt8.self), (PKCS12Data?.length)!)
let keys: [CFString] = [kSecImportExportPassphrase]
let values: [CFTypeRef] = []
let keysPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: keys.count)
keysPointer.initialize(to: keys)
let valuesPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: values.count)
valuesPointer.initialize(to: values)
let optionsDictionary = CFDictionaryCreate(kCFAllocatorDefault, keysPointer, valuesPointer, 1, nil, nil)
var items = CFArrayCreate(kCFAllocatorDefault, UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 0), 0, nil)
let securityError = SecPKCS12Import(inPKCS12Data!, optionsDictionary!, &items)
if (securityError == 0) {
print("Certificate installed Successfully")
} else {
print("Certificate installation failed")
}
}
以上是关于如何以编程方式将证书导入我的iOS应用程序的钥匙串,并在需要时将身份传递给服务器?的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin.iOS VSTS 无法将临时钥匙串添加到钥匙串搜索路径