2013-03-10 3 views
2

Я разрабатываю приложение iOS. У нас есть собственный орган сертификации с самоподписанным ca-cert. Орган сертификации выдает сертификаты как для пользователей, так и для https-сервера. Я хотел бы создать приложение iOS, которое может аутентифицировать https-сервер, используя сертификат ca, а также может связываться с сервером https с использованием сертификата клиента. У меня уже есть код для связи с сервером https с использованием сертификата клиента, но мне нужно, чтобы ca-сертификат импортировался в системный keyring. Я хотел бы иметь сертификат с жестким кодом в приложении. Мой код выглядит так:SecTrustSetAnchorCertificates с сертификатом клиента

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { 

    bool result=NO; 
    if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) { 
     result= YES; 
    } else if([protectionSpace authenticationMethod] ==  NSURLAuthenticationMethodClientCertificate) { 
     result = YES; 
    } 
    return result; 
} 

- (BOOL)shouldTrustProtectionSpace:(NSURLProtectionSpace *)protectionSpace { 
    CFDataRef certDataRef = (__bridge_retained CFDataRef)self.rootCertData; 
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); 

    SecTrustRef serverTrust = protectionSpace.serverTrust; 

    CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)&cert, 1, NULL); 
    SecTrustSetAnchorCertificates(serverTrust, certArrayRef); 

    SecTrustResultType trustResult; 
    SecTrustEvaluate(serverTrust, &trustResult); 

    return trustResult == kSecTrustResultUnspecified; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 

    NSLog(@"Did receive auth challange %@",[challenge debugDescription]); 

    NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; 

    NSString *authMethod = [protectionSpace authenticationMethod]; 
    if(authMethod == NSURLAuthenticationMethodServerTrust) { 
     NSLog(@"Verifying The Trust"); 

     NSURLCredential* cred=[NSURLCredential credentialForTrust:[protectionSpace serverTrust]]; 
     if ([self shouldTrustProtectionSpace:challenge.protectionSpace]) { 
      [[challenge sender] useCredential:cred forAuthenticationChallenge:challenge]; 
      NSLog(@"OK"); 
     } else { 
      NSLog(@"FAILED"); 
      [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; 
     } 

    } 
    if(authMethod == NSURLAuthenticationMethodClientCertificate) { 
     NSLog(@"Trying Certificate"); 
     ..... 

Все работает как шарм, пока сервер не требует сертификата клиента. В этот момент я буду получать сообщение об ошибке сертификата для этого сервера является недействительным и исполнение никогда не достигнет точки

NSLog(@"Trying Certificate"); 

Когда я .der ча-CERT загружены в системе брелока, все работает, даже сертификат клиента отправляется на сервер , и сервер может распознать пользователя. Я вещь, что

SecTrustSetAnchorCertificates(serverTrust, certArrayRef); 

влияет как-то доверие, вызвать, когда я пропустить этот вызов, я могу просто сделать:

[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge]; 

без каких-либо ошибок, но я не в состоянии проверить сертификат в этом случае.

Что я делаю неправильно?

Большое спасибо, Адам

ответ

2

Посмотрите на этот код

https://github.com/dirkx/Security-Pinning-by-CA

, который делает как по довольно тщательно сохраняя два целевых блоков (отдельно, которые вы, кажется, смешивания).