SecTrustEvaluate always returns kSecTrustResultRecoverableTrustFailure with SecPolicyCreateSSL(SecTrustEvaluate 始终使用 SecPolicyCreateSSL 返回 kSecTrustResultRecoverableTrustFailure)
问题描述
我的应用程序尝试为自签名证书评估服务器信任证书.这适用于 SecPolicyCreateBasicX509,但不适用于 SecPolicyCreateSSL
My application tries to evaluate a server trust certificate for a self signed certificate. This is working fine with SecPolicyCreateBasicX509 but not working for SecPolicyCreateSSL
这是我的代码:
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// create trust from protection space
SecTrustRef trustRef;
int trustCertificateCount = SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust);
NSMutableArray* trustCertificates = [[NSMutableArray alloc] initWithCapacity:trustCertificateCount];
for (int i = 0; i < trustCertificateCount; i++) {
SecCertificateRef trustCertificate = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, i);
[trustCertificates addObject:(id) trustCertificate];
}
// set evaluation policy
SecPolicyRef policyRef;
// policyRef = SecPolicyCreateBasicX509(); this is working
policyRef = SecPolicyCreateSSL(NO, (CFStringRef)
SecTrustCreateWithCertificates((CFArrayRef) trustCertificates, policyRef, &trustRef);
[trustCertificates release];
// load known certificates from keychain and set as anchor certificates
NSMutableDictionary* secItemCopyCertificatesParams = [[NSMutableDictionary alloc] init];
[secItemCopyCertificatesParams setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[secItemCopyCertificatesParams setObject:@"Server_Cert_Label" forKey:(id)kSecAttrLabel];
[secItemCopyCertificatesParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
[secItemCopyCertificatesParams setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
CFArrayRef certificates;
certificates = nil;
SecItemCopyMatching((CFDictionaryRef) secItemCopyCertificatesParams, (CFTypeRef*) &certificates);
if (certificates != nil && CFGetTypeID(certificates) == CFArrayGetTypeID()) {
SecTrustSetAnchorCertificates(trustRef, certificates);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
}
SecTrustResultType result;
OSStatus trustEvalStatus = SecTrustEvaluate(trustRef, &result);
if (trustEvalStatus == errSecSuccess) {
if (result == kSecTrustResultConfirm || result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
// evaluation OK
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else {
// evaluation failed
// ask user to add certificate to keychain
} else {
// evaluation failed - cancel authentication
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
经过大量研究,我已经通过添加本文中提到的扩展名对自签名证书进行了更改:无法信任 iphone 上的自签名证书
After a lot of research i have already made changes to the self-signed certificate by adding extension like mentioned in this post: Unable to trust a self signed certificate on iphone
还有人提示这里可能缺少什么吗?
Does anyone have another hint what might be missing here?
推荐答案
经过大量测试,我已经解决了这个问题.以下内容已更改.
After a lot of testing I have worked out this problem. The following has been changed.
该策略设置为 NO 以进行服务器评估.这意味着检查证书以进行客户端身份验证.显然服务器证书不会有这个!将此设置为 YES 将实际检查
extendedKeyUsage
是否为服务器证书设置为serverAuth
.
The policy is set to NO for server evaluation. This means the certificate is checked for client authentication. Obviously the server certificate will not have this! Setting this to YES will actually check if
extendedKeyUsage
is set toserverAuth
for the server certificate.
SecTrustSetAnchorCertificates
和 SecTrustSetAnchorCertificatesOnly
应始终在评估之前调用,而不仅仅是在您提供自己的锚证书时.您需要使用空数组调用它,否则系统已知的锚证书不会用于评估.即使从 MDM 安装的受信任根证书也可以正常工作.
SecTrustSetAnchorCertificates
and SecTrustSetAnchorCertificatesOnly
should always be called before evaluation and not only if you are providing your own anchor certificates. You need to call this with an empty array, otherwise the system known anchor certificates are not used for evaluation. Even installed trusted root certificates from MDM are working then.
这是基于第一个代码的工作示例:
Here is a working sample based on the first code:
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// create trust from protection space
SecTrustRef trustRef;
int trustCertificateCount = SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust);
NSMutableArray* trustCertificates = [[NSMutableArray alloc] initWithCapacity:trustCertificateCount];
for (int i = 0; i < trustCertificateCount; i++) {
SecCertificateRef trustCertificate = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, i);
[trustCertificates addObject:(id) trustCertificate];
}
// set evaluation policy
SecPolicyRef policyRef;
// set to YES to verify certificate extendedKeyUsage is set to serverAuth
policyRef = SecPolicyCreateSSL(YES, (CFStringRef) challenge.protectionSpace.host);
SecTrustCreateWithCertificates((CFArrayRef) trustCertificates, policyRef, &trustRef);
[trustCertificates release];
// load known certificates from keychain and set as anchor certificates
NSMutableDictionary* secItemCopyCertificatesParams = [[NSMutableDictionary alloc] init];
[secItemCopyCertificatesParams setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[secItemCopyCertificatesParams setObject:@"Server_Cert_Label" forKey:(id)kSecAttrLabel];
[secItemCopyCertificatesParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
[secItemCopyCertificatesParams setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
CFArrayRef certificates;
certificates = nil;
SecItemCopyMatching((CFDictionaryRef) secItemCopyCertificatesParams, (CFTypeRef*) &certificates);
if (certificates != nil && CFGetTypeID(certificates) == CFArrayGetTypeID()) {
SecTrustSetAnchorCertificates(trustRef, certificates);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
} else {
// set empty array as own anchor certificate so system anchos certificates are used too!
SecTrustSetAnchorCertificates(trustRef, (CFArrayRef) [NSArray array]);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
}
SecTrustResultType result;
OSStatus trustEvalStatus = SecTrustEvaluate(trustRef, &result);
if (trustEvalStatus == errSecSuccess) {
if (result == kSecTrustResultConfirm || result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
// evaluation OK
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else {
// evaluation failed
// ask user to add certificate to keychain
}
}
else {
// evaluation failed - cancel authentication
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
希望这会对某人有所帮助.
Hope this will help someone.
这篇关于SecTrustEvaluate 始终使用 SecPolicyCreateSSL 返回 kSecTrustResultRecoverableTrustFailure的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:SecTrustEvaluate 始终使用 SecPolicyCreateSSL 返回 kSecT


- 想使用ViewPager,无法识别android.support.*? 2022-01-01
- Android viewpager检测滑动超出范围 2022-01-01
- MalformedJsonException:在第1行第1列路径中使用JsonReader.setLenient(True)接受格式错误的JSON 2022-01-01
- 如何检查发送到 Android 应用程序的 Firebase 消息的传递状态? 2022-01-01
- 在测试浓缩咖啡时,Android设备不会在屏幕上启动活动 2022-01-01
- 用 Swift 实现 UITextFieldDelegate 2022-01-01
- Android - 拆分 Drawable 2022-01-01
- Android - 我如何找出用户有多少未读电子邮件? 2022-01-01
- 使用自定义动画时在 iOS9 上忽略 edgesForExtendedLayout 2022-01-01
- android 4中的android RadioButton问题 2022-01-01