iOS 证书、密钥及信任服务
——翻译自Apple Reference《Certificate,Key,andTrust Services Programming Guide》
本章描述并演示了如何使用证书、密钥和信任服务去导入一个indentity,评估证书是否可信,判断证书失效的原因,以及失效证书的恢复。
本章按如下顺序分别演示了:
导入一个identity.
从导入的数据中获得证书.
获得用于证书评估的策略.
校验证书,根据指定策略评估证书是否可信.
测试证书中的可恢复错误.
判断证书是否过期.
改变评估条件,忽略过期证书.
重新评估证书.
“第2章,Certificate,Key,and TrustServices Concepts”,介绍了证书,密钥和信任服务的概念和术语。关于证书,密钥和信任服务的细节内容,请参考Certificate,Key,andTrust Services Reference.
从一个.p12文件中提取、评估Identity
如果你需要在iOS设备上使用加密过的identity(一个密钥及其关联的证书)进行客户端认证,例如——你可以把PKCS#12数据以受密码保护的文件的方式安全地传输到这个设备上。本节显示如何从PKCS#12数据中提取identity和trustobjects(可信任对象),并评估其可信度。
列表 2-1 显示了用SecPKCS12Import函数从.p12文件中提取identity和可信任对象,以及评估其可信度。
列表 2-2 显示如何从identity中获取证书并显示证书信息。每个列表后都对代码进行了解释。
在编译这段代码时,请确认在Xcode工程中加入了Security.framework。
列表 2-1 从PKCS#12数据中提取identity和trust对象
#import <UIKit/UIKit.h>
#import <Security/Security.h>
#import<CoreFoundation/CoreFoundation.h>
NSString *thePath = [[NSBundle mainBundle]
pathForResource:@"MyIdentity" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc]initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data =(CFDataRef)PKCS12Data; // 1
OSStatus status = noErr;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
status = extractIdentityAndTrust(
inPKCS12Data,
&myIdentity,
&myTrust); // 2
if status != 0 ... //Do some error checking here
SecTrustResultType trustResult;
if(status == noErr) { // 3
status =SecTrustEvaluate(myTrust, &trustResult);
}
... // 4
if (trustResult ==kSecTrustResultRecoverableTrustFailure) {
...;
}
OSStatus extractIdentityAndTrust(CFDataRefinPKCS12Data, // 5
SecIdentityRef *outIdentity,
SecTrustRef *outTrust)
{
OSStatus securityError = errSecSuccess;
CFStringRef password =CFSTR("Password");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary =CFDictionaryCreate(
NULL,keys,
values, 1,
NULL, NULL); // 6
CFArrayRef items = CFArrayCreate(NULL, 0, 0,NULL);
securityError = SecPKCS12Import(inPKCS12Data,
optionsDictionary,
&items); // 7
//
if (securityError == 0) { // 8
CFDictionaryRefmyIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity= NULL;
tempIdentity =CFDictionaryGetValue (myIdentityAndTrust,
kSecImportItemIdentity);
*outIdentity =(SecIdentityRef)tempIdentity;
const void *tempTrust =NULL;
tempTrust =CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
*outTrust =(SecTrustRef)tempTrust;
}
if (optionsDictionary)
CFRelease(optionsDictionary); //9
[PKCS12Data release];
在这段代码中:
检索PKCS#12文件并获得数据。本例中,该文件位于applicationbundle中。你也可以通过网络方式把文件传输给你的应用程序。
调用该函数获得identity和trust对象(见步骤5)。
评估证书。这里的信任对象(trust object),包括信任策略和其他用于判断证书是否可信的信息,都已经含在了PKCS数据中。要单独评估一个证书是否可信,见列表2-6。
处理信任结果。如果信任结果是kSecTrustResultInvalid,kSecTrustResultDeny,kSecTrustResultFatalTrustFailure,你无法进行处理。如果评估结果是kSecTrustResultRecoverableTrustFailure,你可以从信任失败中恢复。参见“从信任失败中恢复”。