Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在iOS中验证(并要求)自签名证书_Ios_Security_Ssl_Openssl_Ssl Certificate - Fatal编程技术网

如何在iOS中验证(并要求)自签名证书

如何在iOS中验证(并要求)自签名证书,ios,security,ssl,openssl,ssl-certificate,Ios,Security,Ssl,Openssl,Ssl Certificate,我想使用iOS中代码附带的自签名证书创建到服务器的SSL连接。这样,我就不必担心更复杂的中间人攻击,即有人可以访问高级“可信”证书颁发机构。使用我认为是苹果的标准方式,我在这样做时遇到了问题 通过找到的过程生成证书 以及iOS代码: - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

我想使用iOS中代码附带的自签名证书创建到服务器的SSL连接。这样,我就不必担心更复杂的中间人攻击,即有人可以访问高级“可信”证书颁发机构。使用我认为是苹果的标准方式,我在这样做时遇到了问题

通过找到的过程生成证书

以及iOS代码:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
  if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
    // Load anchor cert.. also tried this with both certs and it doesn't seem to matter
    NSString *path = [[NSBundle mainBundle] pathForResource:@"root.der" ofType:@"crt"];
    NSData *data = [[NSData alloc] initWithContentsOfFile:path];
    SecCertificateRef anchorCert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data);
    CFMutableArrayRef anchorCerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
    CFArrayAppendValue(anchorCerts, anchorCert);

    // Set anchor cert
    SecTrustRef trust = [protectionSpace serverTrust];
    SecTrustSetAnchorCertificates(trust, anchorCerts);
    SecTrustSetAnchorCertificatesOnly(trust, YES); // only use that certificate
    CFRelease(anchorCert);
    CFRelease(anchorCerts);

    // Validate cert
    SecTrustResultType secresult = kSecTrustResultInvalid;
    if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) {
      [challenge.sender cancelAuthenticationChallenge:challenge];
      return;
    }

    switch (secresult) {
      case kSecTrustResultInvalid:
      case kSecTrustResultDeny:
      case kSecTrustResultFatalTrustFailure:
      case kSecTrustResultOtherError:
      case kSecTrustResultRecoverableTrustFailure: { 
        // !!! It's always kSecTrustResultRecoverableTrustFailure, aka 5
        NSLog(@"Failing due to result: %lu", secresult);
        [challenge.sender cancelAuthenticationChallenge:challenge];
        return;
      }

      case kSecTrustResultUnspecified: // The OS trusts this certificate implicitly.
      case kSecTrustResultProceed: { // The user explicitly told the OS to trust it.
        NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
        return;
      }
      default: ;
        /* It's somebody else's key. Fall through. */
    }
    /* The server sent a key other than the trusted key. */
    [connection cancel];

    // Perform other cleanup here, as needed.
  } else {
    NSLog(@"In weird space... not handling authentication method: %@", [protectionSpace authenticationMethod]);
    [connection cancel];
  }
}
我总是得到kSecTrustResultRecoverableTrustFailure作为结果。我不认为这是本地主机的问题,因为我已经尝试使用苹果的代码来改变这一点。怎么办

谢谢

如果信任结果为kSecTrustResultRecoverableTrustFailure,则您可能能够从失败中恢复

这里是解决方法


请确保您的证书有效。我想它的名字不应该是root.der.crt。您可以从中查找证书类型。以下代码是p12证书的代码,希望对您有所帮助

NSData *PKCS12DataQA = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"CERTIFICATE NAME" ofType:@"CERTIFICATE TYPE"]];

BOOL result = [self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12DataQA];


- (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data
{
    OSStatus securityError = errSecSuccess;
    //testtest is the passsword for the certificate.
    NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"testtest" forKey:(id)CFBridgingRelease(kSecImportExportPassphrase)];

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import((__bridge CFDataRef)(inPKCS12Data),(CFDictionaryRef)CFBridgingRetain(optionsDictionary),&items);

    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
        *outTrust = (SecTrustRef)tempTrust;

    } else {
        NSLog(@"Failed with error code %d",(int)securityError);
        return NO;
    }

    return YES;
}

您需要覆盖针对ProtectionSpace的
CanAuthentication和
didReceiveAuthenticationChallenge
TrustResultRecoverableTrustFailure
表示您可以更改服务器验证的结果。另请参见位于的OWASP的iOS公钥锁定示例。
NSData *PKCS12DataQA = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"CERTIFICATE NAME" ofType:@"CERTIFICATE TYPE"]];

BOOL result = [self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12DataQA];


- (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data
{
    OSStatus securityError = errSecSuccess;
    //testtest is the passsword for the certificate.
    NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"testtest" forKey:(id)CFBridgingRelease(kSecImportExportPassphrase)];

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import((__bridge CFDataRef)(inPKCS12Data),(CFDictionaryRef)CFBridgingRetain(optionsDictionary),&items);

    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
        *outTrust = (SecTrustRef)tempTrust;

    } else {
        NSLog(@"Failed with error code %d",(int)securityError);
        return NO;
    }

    return YES;
}