Двухсторонний SSL с NSURLConnection на iOS 5 - PullRequest
5 голосов
/ 03 апреля 2012

Я пытаюсь, чтобы UIWebView обращался к веб-сайту https, запрашивая сертификат клиента для двухстороннего SSL. Моей отправной точкой была документация Apple: Руководство по программированию сертификатов, ключей и доверенных служб Существует также много справок по работе с стеком.

Я придумал следующий код для ответа на запрос аутентификации, загрузил файл идентификации p12 и промежуточные сертификаты crt, а затем представил их.

-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"Auth method: %@", challenge.protectionSpace.authenticationMethod);
if([challenge previousFailureCount] <5) {
    NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
    NSString *authMethod = [protectionSpace authenticationMethod];
    if(authMethod == NSURLAuthenticationMethodServerTrust ) {
        NSLog(@"Verifying The Trust");
        [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[protectionSpace serverTrust]] forAuthenticationChallenge:challenge];
    } else if(authMethod == NSURLAuthenticationMethodClientCertificate ) {
        NSLog(@"Getting client certificate");
        SecIdentityRef identity = [self getClientCertificate:@"mycert" withPassword:@"password"];
        SecCertificateRef intermediateCert = [self getCertificate:@"intermediatecert"];
        SecCertificateRef rootCA = [self getCertificate:@"cacert"];

        NSMutableArray *combinedCerts = [NSMutableArray array];
        [combinedCerts addObject:(__bridge id)intermediateCert];
        [combinedCerts addObject:(__bridge id)rootCA];

        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:combinedCerts persistence:NSURLCredentialPersistencePermanent];

        NSLog(@"Sending credential");
        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
    } else {
        NSLog(@"Not dealing with challenge %@",authMethod);
    }
} else {
    NSLog(@"Auth Challenge Failed");
    [[challenge sender] cancelAuthenticationChallenge:challenge];
}
}

Результаты, ну ... не очень хорошие. Вызов завершается с ошибкой рукопожатия. Вызов сайта с хромом и тем же сертификатом на самом деле работает нормально, что заставило меня проверить в Wireshark, в чем разница между двумя вызовами.

С Chrome все выглядит нормально, как и для рукопожатия TLS.

iOS работает с TLSv1 и Chrome с SSLv3: это не должно быть проблемой. Что более интригующе, так это то, что моя программа отправляет по какой-то причине пустое рукопожатие с сертификатом msg:

Frame 102: 66 bytes on wire (528 bits), 66 bytes captured (528 bits)
Ethernet II, Src: Apple_XX:XX:XX (XX:XX:XX:XX:XX:XX), Dst: Cisco-Li_3d:96:d0 (XX:XX:XX:XX:XX:XX)
Internet Protocol Version 4, Src: imac.local (192.168.1.9), Dst: xxx.xxx.xxx (xxx.xxx.xxx.xxx)
Transmission Control Protocol, Src Port: 63324 (63324), Dst Port: https (443), Seq: 187, Ack: 4244, Len: 12
Secure Sockets Layer
TLSv1 Record Layer: Handshake Protocol: Certificate
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 7
    Handshake Protocol: Certificate
        Handshake Type: Certificate (11)
        Length: 3
        Certificates Length: 0

, а затем второй с правильным содержанием:

Frame 108: 248 bytes on wire (1984 bits), 248 bytes captured (1984 bits)
Ethernet II, Src: Apple_XX:XX:XX (XX:XX:XX:XX:XX:XX), Dst: Cisco-Li_XX:XX:XX (XX:XX:XX:XX:XX)
Internet Protocol Version 4, Src: imac.local (192.168.1.9), Dst: xxx.xxx.xxx (xxx.xxx.xxx.xxx)
Transmission Control Protocol, Src Port: 63325 (63325), Dst Port: https (443), Seq: 2947, Ack: 4244, Len: 194
[3 Reassembled TCP Segments (2954 bytes): #106(1380), #107(1380), #108(194)]
Secure Sockets Layer
TLSv1 Record Layer: Handshake Protocol: Certificate
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 2949
    Handshake Protocol: Certificate
        Handshake Type: Certificate (11)
        Length: 2945
        Certificates Length: 2942
        Certificates (2942 bytes)
            Certificate Length: 1024
            Certificate (id-at-organizationName=XX,id-at-organizationalUnitName=XX,id-at-serialNumber=XX,id-at-countryName=XX,id-at-commonName=XXXXXX)
            Certificate Length: 995
            Certificate (id-at-serialNumber=XX,id-at-commonName=XXXX,id-at-countryName=XX)
            Certificate Length: 914
            Certificate (id-at-commonName=XXXX,id-at-countryName=XX)

Кто-нибудь когда-нибудь видел что-то подобное?

Я почти уверен, что где-то допустил какую-то действительно глупую ошибку, поскольку некоторые другие люди с почти таким же кодом справляются с тем, чего добиваются уже несколько дней ...

...