iOS导入自签名和自行创建的CA证书
问题描述:
我已经将自签名X509证书导入到我的iPhone中,只需将certificate.pem发送给它并安装到设备上即可。现在我想验证我的iOS应用程序中必须使用上述证书签名的特定证书。基本上,导入的证书充当CA的根证书。iOS导入自签名和自行创建的CA证书
导入的证书是否存储在钥匙串中?
如何以编程方式验证基于导入的另一个证书? (第二个证书只有在被导入前的CA证书签名时才有效)
有没有人有过这些场景的经验?
在此先感谢!
答
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进行比较,以确保对其进行验证。
谢谢!正是我在找什么。顺便说一下,是否也可以从钥匙串中获取/提取整个证书? (例如,如果您在代码中将NSData用作钥匙串中的NSData,但它是使用Apple的iPhone配置实用程序或任何其他MDM部署的?) – Chris 2012-07-20 17:59:14
是的 - 下面是我使用的代码。实际上,如果你需要一个预先确定的标识符,它实际上会多一点。对不起,格式化 - 但评论是有点困难的代码。随意创建一个问题,以便我可以正确剪切和粘贴。 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
我试过你的代码(和Apple的示例代码),但它总是在'SecTrustEvaluate'上崩溃。新帖子:http://stackoverflow.com/questions/11608847/always-exc-bad-access-on-sectrustevaluate – Chris 2012-07-23 08:26:27