Ios 使用证书创建SSL连接

Ios 使用证书创建SSL连接,ios,objective-c,ssl,nsurlconnection,Ios,Objective C,Ssl,Nsurlconnection,我有作为文件提供给我的ssl证书(.cer)。 我将它添加到bundle中,并希望使用它与服务器通信 我使用苹果提供的代码: - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{ DLog(@"didReceiveAuthenticationChallenge : %@",challenge)

我有作为文件提供给我的ssl证书(.cer)。 我将它添加到bundle中,并希望使用它与服务器通信

我使用苹果提供的代码:

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
    DLog(@"didReceiveAuthenticationChallenge : %@",challenge);
    if ([challenge.protectionSpace.authenticationMethod
         isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"];
        NSData *certData = [NSData dataWithContentsOfFile:filePath];
        CFDataRef myCertData = (__bridge CFDataRef)certData; 
        SecCertificateRef myCert = SecCertificateCreateWithData(NULL,
                                                                myCertData);
        SecPolicyRef myPolicy = SecPolicyCreateBasicX509();         // 3
        SecCertificateRef certArray[1] = { myCert };
        CFArrayRef myCerts = CFArrayCreate(NULL,
                                           (void *)certArray,
                                           1,
                                           NULL);
        SecTrustRef myTrust;
        OSStatus status = SecTrustCreateWithCertificates(
                                                         myCerts,
                                                         myPolicy,
                                                         &myTrust);  // 4
        SecTrustResultType trustResult = 0;
        if (status == noErr) {
            status = SecTrustEvaluate(myTrust, &trustResult);       // 5
        }
        // If the trust result is kSecTrustResultInvalid, kSecTrustResultDeny, kSecTrustResultFatalTrustFailure, you cannot proceed and should fail gracefully.
        BOOL proceed = NO;
        switch (trustResult) {
            case kSecTrustResultProceed: // 1
                DLog(@"Proceed");
                proceed = YES;
                break;
            case kSecTrustResultConfirm: // 2
                DLog(@"Confirm");
                proceed = YES;
                break;
            case kSecTrustResultUnspecified: // 4
                DLog(@"Unspecified");
                break;
            case kSecTrustResultRecoverableTrustFailure:  // 5
                DLog(@"TrustFailure");
                proceed = [self recoverFromTrustFailure:myTrust];
                break;
            case kSecTrustResultDeny: // 3
                DLog(@"Deny");
                break;
            case kSecTrustResultFatalTrustFailure: // 6
                DLog(@"FatalTrustFailure");
                break;
            case kSecTrustResultOtherError: // 7
                DLog(@"OtherError");
                break;
            case kSecTrustResultInvalid: // 0
                DLog(@"Invalid");
                break;
            default:
                DLog(@"Default");
                break;
        }
        if (myPolicy)
            CFRelease(myPolicy);
        if (proceed) {
            [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
        }else{
            [[challenge sender] cancelAuthenticationChallenge:challenge];
        }
    }
}

- (BOOL) recoverFromTrustFailure:(SecTrustRef) myTrust
{
    SecTrustResultType trustResult;
    OSStatus status = SecTrustEvaluate(myTrust, &trustResult);  // 1
    //Get time used to verify trust
    CFAbsoluteTime trustTime,currentTime,timeIncrement,newTime;
    CFDateRef newDate;
    if (trustResult == kSecTrustResultRecoverableTrustFailure) {// 2
        trustTime = SecTrustGetVerifyTime(myTrust);             // 3
        timeIncrement = 31536000;                               // 4
        currentTime = CFAbsoluteTimeGetCurrent();               // 5
        newTime = currentTime - timeIncrement;                  // 6
        if (trustTime - newTime){                               // 7
            newDate = CFDateCreate(NULL, newTime);              // 8
            SecTrustSetVerifyDate(myTrust, newDate);            // 9
            status = SecTrustEvaluate(myTrust, &trustResult);   // 10
        }
    }
    if (trustResult != kSecTrustResultProceed) {
        DLog(@"Failed with status : %li",trustResult);               // 11
        return NO;
    }else{
        DLog(@"Procced");
        return YES;
    }
}
但是,我得到了ksectrustsresultrecoverabletrustfailure。在这种情况下也使用了apple示例,但没有任何帮助

也许有人能帮我


谢谢。

如果这是用于服务器信任身份验证的自签名证书,则应执行以下操作:

  • 将.CRT编码的证书转换为.DER编码的证书。在终端类型上:

    $:openssl x509-in certificate.crt-outform der-out“com.server.trust\u cert.der”

    (选择您自己有意义的名称)

    将.DER编码的证书放入捆绑包中

  • 实现方法
    连接:didReceiveAuthenticationChallenge:
    ,如下所示。 重要提示:始终检查错误并退出,如果出现任何错误,则让身份验证失败

    彻底测试它

  • 注: 上述技术的一个可能改进是使用“公钥锁定”

    必须阅读: (苹果官方文件,技术说明TN2232)


    (苹果官方参考文档)

    该证书是为您的客户端准备的,还是您应该信任的服务器证书?我应该信任此证书。事实上,我没有这方面的经验,所以我可能会胡说八道。但这里是比较文件大小(字节)。所以,若某个服务器的文件大小与应用程序中的证书大小相同,那个么它将被信任吗?我在这里找到了更多信息:否。
    [server\u cert isequaldata:my\u cert]
    仅当两个字节序列相等时才计算为
    YES
    。这是一个逐字节的比较。长度也必须相同。您可能会发现这一点很有用:以下是Apple开发者论坛(requires account)上专门针对您的问题的帖子:Quinn在这里给出了确切的答案:
    - (void)connection:(NSURLConnection *)connection
        didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {
        if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust])
        {
            do
            {
                SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
                if (serverTrust == nil)
                    break; // failed
    
                SecTrustResultType trustResult;
                OSStatus status = SecTrustEvaluate(serverTrust, &trustResult);
                if (!(errSecSuccess == status))
                    break; // fatal error in trust evaluation -> failed
    
                if (!((trustResult == kSecTrustResultProceed) 
                   || (trustResult == kSecTrustResultUnspecified)))
                {
                    break; // see "Certificate, Key, and Trust Services Reference" 
                           // for explanation of result codes.
                }
    
                SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
                if (serverCertificate == nil)
                    break; // failed
    
                CFDataRef serverCertificateData = SecCertificateCopyData(serverCertificate);
                if (serverCertificateData == nil)
                    break; // failed
    
                const UInt8* const data = CFDataGetBytePtr(serverCertificateData);
                const CFIndex size = CFDataGetLength(serverCertificateData);
                NSData* server_cert = [NSData dataWithBytes:data length:(NSUInteger)size];
                CFRelease(serverCertificateData);
    
                NSString* file = [[NSBundle mainBundle] pathForResource:@"com.server.trust_cert"
                                                                 ofType:@"der"];
                NSData* my_cert = [NSData dataWithContentsOfFile:file];
    
                if (server_cert == nil || my_cert == nil)
                    break; // failed
    
                const BOOL equal = [server_cert isEqualToData:my_cert];
                if (!equal)
                    break; // failed 
    
                // Athentication succeeded:
                return [[challenge sender] useCredential:[NSURLCredential credentialForTrust:serverTrust]
                              forAuthenticationChallenge:challenge];
            } while (0);
    
            // Authentication failed: 
            return [[challenge sender] cancelAuthenticationChallenge:challenge];
        }
    }