【问题标题】:iOS import self-signed and self-created CA certificatesiOS 导入自签名自建 CA 证书
【发布时间】:2012-07-19 18:16:31
【问题描述】:

我已将自签名 X509 证书导入我的 iPhone,只需通过电子邮件将 certificate.pem 发送给它并将其安装在设备上。现在我想在我的 iOS 应用程序中验证必须使用上述证书签名的特定证书。基本上,导入的证书充当 CA 的根证书。

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

如何根据导入的证书以编程方式验证另一个证书? (第二个证书只有经过之前导入的CA证书签名才有效)

有人对这些场景有一些经验吗?

提前致谢!

【问题讨论】:

    标签: iphone validation certificate x509 trust


    【解决方案1】:

    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();然后是 NSData 的 SHA1 与您的硬编码 sha1 进行比较,以确保它与那个完全一致。

    【讨论】:

    • 谢谢!正是我想要的。顺便说一句,是否也可以从钥匙串中获取/提取整个证书? (例如,如果您需要它作为钥匙串之外的代码中的 NSData,但它是使用苹果的 iPhone 配置实用程序或任何其他 MDM 部署的?)
    • 是的 - 下面是我使用的代码。如果你需要一个持久标识符,它实际上会更多。抱歉格式化 - 但 cmets 在代码上有点难。随意创建一个问题,以便我可以正确剪切和粘贴。 CFDictionaryCreate(), SecItemCopyMatching(), 检查 SecIdentityGetTypeID() cast, CFDataRef der = SecCertificateCopyData(cert); const unsigned char * ptr = CFDataGetBytePtr(der);长 len = CFDataGetLength(der); d2i_X509(&x509,&ptr,len); _sha1 = [(__bridge NSData *)der sha1]; _der = (__bridge_transfer NSData *) der; CFRelease(der);
    • 我已经尝试过您的代码(以及 Apple 的示例代码),但它总是在 SecTrustEvaluate 上崩溃。新帖:stackoverflow.com/questions/11608847/…
    • 我能够从 .p12 数据文件中加载身份,并使用上述内容获取用于加密数据的公钥。我不需要打电话给SecTrustSetAnchorCertificates,只需要在SecTrustCopyPublicKey 之前打电话给SecTrustEvaluate。谢谢!
    • 是的 - 这取决于政策。有关更完整的示例,请参阅github.com/dirkx/Security-Pinning-by-CA - 这对这方面非常明确。
    猜你喜欢
    • 2020-07-30
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 2017-03-15
    • 2016-07-08
    • 2016-01-22
    相关资源
    最近更新 更多