You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS如何检测根证书已安装且被用户手动信任?

检测iOS用户是否手动信任根CA证书

我完全理解你的困扰——SecTrustEvaluate的返回结果在不同iOS版本里表现不一致,而且没法区分是系统默认信任还是用户手动在「通用->关于本机->信任设置」里确认的状态。这里有几个经过验证的可行方案,帮你精准检测用户的手动信任操作:

方案1:查询证书的kSecAttrIsUserTrusted属性

这个系统属性会明确标记证书是否是用户手动在设置中确认信任的,不受iOS版本差异影响。你可以通过SecItemCopyMatching查询已安装证书的该属性:

BOOL isUserManuallyTrusted(SecCertificateRef cert) {
    BOOL result = NO;
    NSDictionary *query = @{
        (__bridge NSString *)kSecClass: (__bridge NSString *)kSecClassCertificate,
        (__bridge NSString *)kSecValueRef: (__bridge id)cert,
        (__bridge NSString *)kSecReturnAttributes: @YES
    };
    
    CFDictionaryRef attributes = NULL;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&attributes);
    
    if (status == errSecSuccess) {
        NSNumber *isUserTrusted = (__bridge NSNumber *)CFDictionaryGetValue(attributes, kSecAttrIsUserTrusted);
        result = [isUserTrusted boolValue];
        CFRelease(attributes);
    }
    
    return result;
}

方案2:结合SecTrustEvaluateWithError做完整验证

在iOS 12及以上,推荐使用更现代的SecTrustEvaluateWithError API,同时搭配上面的属性检查,确保信任链中确实包含用户手动信任的根CA:

BOOL checkManualUserTrust(SecCertificateRef fullChain) {
    SecPolicyRef policy = SecPolicyCreateBasicX509();
    SecTrustRef trust = NULL;
    OSStatus status = SecTrustCreateWithCertificates(fullChain, policy, &trust);
    
    if (status != errSecSuccess) {
        CFRelease(policy);
        return NO;
    }
    
    NSError *error = nil;
    BOOL trustResult = SecTrustEvaluateWithError(trust, &error);
    BOOL isManualTrust = NO;
    
    if (trustResult) {
        // 遍历信任链,检查是否存在用户手动信任的证书
        CFIndex certCount = SecTrustGetCertificateCount(trust);
        for (CFIndex i = 0; i < certCount; i++) {
            SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
            if (isUserManuallyTrusted(cert)) {
                isManualTrust = YES;
                break;
            }
        }
    }
    
    CFRelease(trust);
    CFRelease(policy);
    return isManualTrust;
}

关键注意事项

  • kSecAttrIsUserTrusted仅对用户手动安装的配置文件中的根CA生效,系统预装的根证书不会带有这个标记。
  • 测试时要注意:安装配置文件后未手动信任,该属性为NO;用户手动信任后变为YES;卸载配置文件后该标记会被清除。
  • iOS 10及以上系统无需额外权限即可查询该属性,但确保你的应用代码中已正确导入Security框架。

内容的提问来源于stack exchange,提问作者Al Ga

火山引擎 最新活动