我已将自签名 X509 证书导入我的 iPhone,只需通过电子邮件将 certificate.pem 发送给它并将其安装在设备上。现在我想在我的 iOS 应用程序中验证必须使用上述证书签名的特定证书。基本上,导入的证书充当 CA 的根证书。
导入的证书是否存储在钥匙串中?
如何基于导入的证书以编程方式验证另一个证书?(第二个证书只有由之前导入的CA证书签名才有效)
有没有人对这些场景有一些经验?
提前致谢!
我已将自签名 X509 证书导入我的 iPhone,只需通过电子邮件将 certificate.pem 发送给它并将其安装在设备上。现在我想在我的 iOS 应用程序中验证必须使用上述证书签名的特定证书。基本上,导入的证书充当 CA 的根证书。
导入的证书是否存储在钥匙串中?
如何基于导入的证书以编程方式验证另一个证书?(第二个证书只有由之前导入的CA证书签名才有效)
有没有人对这些场景有一些经验?
提前致谢!
1)是的 - 它位于您的钥匙串中。
2)您使用 trust 验证它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 进行比较,以确保它完全针对那个进行验证。