2012-07-20 80 views
2

我已经将自签名X509证书导入到我的iPhone中,只需将certificate.pem发送给它并安装到设备上即可。现在我想验证我的iOS应用程序中必须使用上述证书签名的特定证书。基本上,导入的证书充当CA的根证书。iOS导入自签名和自行创建的CA证书

导入的证书是否存储在钥匙串中?

如何以编程方式验证基于导入的另一个证书? (第二个证书只有在被导入前的CA证书签名时才有效)

有没有人有过这些场景的经验?

在此先感谢!

回答

3

1)是 - 它坐落在您的钥匙串中。

2)您使用信任SecTrustCreateWithCertificates()SecTrustEvaluate()针对所有证书或您自己的证书对其进行验证。 3)如果您通过一系列的证书对其进行验证,您可以选择在钥匙串中查找自己的证书;得到DER;计算其SHA1并将其与您的代码中硬编码的SHA1进行比较。

代码如下所示。

NSMutableArray *serverChain = -- array with what you want to check 
NSMutableArray *trustedCertRefs = <your-hardcoded-certs>; 

SecTrustRef noHostTrustRef = NULL; 
OSErr status = SecTrustCreateWithCertificates((__bridge CFArrayRef)serverChain, 
           SecPolicyCreateSSL(NO, nil), &noHostTrustRef); 

if (status != noErr) { 
    NSLog(@"SecTrustCreateWithCertificates failed: %hd", status); 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 
} 


status = SecTrustSetAnchorCertificates(noHostTrustRef, 
         (__bridge CFArrayRef)trustedCertRefs); 
if (status != noErr) { 
    NSLog(@"SecTrustSetAnchorCertificates failed: %hd", status); 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 
} 

status = SecTrustEvaluate(noHostTrustRef, &result); 
if (status != noErr) { 
    NSLog(@"SecTrustEvaluate failed: %hd", status); 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 
} 
CFRelease(noHostTrustRef); 

/* From SecTrust.h: 
* 
* SecTrustResultType results have two dimensions. They specify both whether 
* evaluation suceeded and whether this is because of a user decision. 
* 
* In practice the commonly expected result is kSecTrustResultUnspecified, 
* which indicates a positive result that wasn't decided by the user. 
* 
* The common failure is kSecTrustResultRecoverableTrustFailure, which means a 
* negative result. kSecTrustResultProceed and kSecTrustResultDeny are the 
* positive and negative result respectively when decided by the user. User 
* decisions are persisted through the use of SecTrustCopyExceptions() and 
* SecTrustSetExceptions(). Finally kSecTrustResultFatalTrustFailure is a 
* negative result that should not be circumvented. In fact only in the case 
* of kSecTrustResultRecoverableTrustFailure should a user ever be asked. 
*/ 
switch (result) { 
    case kSecTrustResultProceed: // 1 
    case kSecTrustResultConfirm: // 2 
    case kSecTrustResultUnspecified: // 4 
     return YES 
     break; 
    case kSecTrustResultRecoverableTrustFailure: // 5 
    case kSecTrustResultDeny: // 3 
    case kSecTrustResultFatalTrustFailure: // 6 
    case kSecTrustResultOtherError: // 7 
    case kSecTrustResultInvalid: // 0 
    default: 
     return NO: 
     break; 
} 
[[challenge sender] cancelAuthenticationChallenge:challenge]; 

,或者如果你得到一个信任链,从它(对你的证书,因此)已经证实对钥匙扣网络堆栈说 - 那么你可以提取证书;对他们做一个SecCertificateCopyData();然后SHA1 NSData与您的硬编码sha1进行比较,以确保对其进行验证。

+0

谢谢!正是我在找什么。顺便说一下,是否也可以从钥匙串中获取/提取整个证书? (例如,如果您在代码中将NSData用作钥匙串中的NSData,但它是使用Apple的iPhone配置实用程序或任何其他MDM部署的?) – Chris 2012-07-20 17:59:14

+1

是的 - 下面是我使用的代码。实际上,如果你需要一个预先确定的标识符,它实际上会多一点。对不起,格式化 - 但评论是有点困难的代码。随意创建一个问题,以便我可以正确剪切和粘贴。 CFDictionaryCreate(),SecItemCopyMatching(),检查SecIdentityGetTypeID()强制转换,CFDataRef der = SecCertificateCopyData(cert); const unsigned char * ptr = CFDataGetBytePtr(der); long len = CFDataGetLength(der); d2i_X509(&x509,&ptr,len); _sha1 = [(__bridge NSData *)der sha1]; _der =(__bridge_transfer NSData *)der; CFRelease(der); – 2012-07-22 10:39:27

+0

我试过你的代码(和Apple的示例代码),但它总是在'SecTrustEvaluate'上崩溃。新帖子:http://stackoverflow.com/questions/11608847/always-exc-bad-access-on-sectrustevaluate – Chris 2012-07-23 08:26:27