使用证书创buildSSL连接

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

我用苹果提供的代码:

- (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; } } 

但是我越来越kSecTrustResultRecoverableTrustFailure 。 在这种情况下也使用苹果样品,但没有帮助。

也许有人可以帮助我呢?

谢谢。

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

  1. 将.CRT编码证书转换为.DER编码证书。 在terminaltypes上:

    $: openssl x509 -in certificate.crt -outform der -out "com.server.trust_cert.der"

    (select你自己有意义的名字)

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

  2. 实现方法connection:didReceiveAuthenticationChallenge:如下。 重要提示:请始终检查错误并进行保释,如果有任何错误,请authentication失败!

    彻底testing!

 - (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]; } } 

注意:

上述技术的一个可能的改进是使用“公钥固定”。

必须阅读:

HTTPS服务器信任评估 (官方Apple文档,技术说明TN2232)

证书,密钥和信任服务参考 (官方Apple参考文档)