Я пытаюсь, чтобы 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)
Кто-нибудь когда-нибудь видел что-то подобное?
Я почти уверен, что где-то допустил какую-то действительно глупую ошибку, поскольку некоторые другие люди с почти таким же кодом справляются с тем, чего добиваются уже несколько дней ...