SSL Socket соединение iOS
Я пытаюсь настроить безопасное соединение с Java SSNerverSocket.
Я создал свой собственный корневой центр сертификации и подписал сертификат о том, что Java SSLServerSocket использует этот сертификат.
Я хочу добавить этот корневой сертификат в свое приложение, чтобы любой сертификат, подписанный корневым сертификатом, работал.
Пока у меня есть безопасное соединение, работающее нормально, установив свойства потока чтения и записи в это:
NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
(id)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamPropertySocketSecurityLevel,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,nil];
Я добавляю сертификат в связку ключей следующим образом:
-(void)addRootCert{
NSString* rootCertPath = [[NSBundle mainBundle] pathForResource:@"rootCA" ofType:@"der"];
NSData* rootCertData = [NSData dataWithContentsOfFile:rootCertPath];
OSStatus err = noErr;
SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)rootCertData);
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge_transfer id)kSecClassCertificate, kSecClass, rootCert, kSecValueRef, nil];
err = SecItemAdd((__bridge CFDictionaryRef) dict, NULL);
if (err == noErr) {
NSLog(@"Sucessfully added root certificate");
}else if (err == errSecDuplicateItem){
NSLog(@"Root certificate already exists");
}else{
NSLog(@"Root certificate add failed");
}
}
Это нормально, но я хочу проверить цепочку сертификатов, чтобы мое приложение принимало только сертификаты, подписанные моим ЦС (или доверенными сертификатами по умолчанию)
Как я могу это сделать?
Если я установлю kCFStreamSSLValidatesCertificateChain
да, я получаю ошибку: CFNetwork SSLHandshake failed (-9807)
но если это не так, не имеет значения, кто подписал сертификат сервера, он будет подключаться независимо (я полагаю, что это правильно?)
Спасибо!
2 ответа
В техническом замечании 2232"Оценка доверия сервера HTTPS" должны быть найдены все ответы, которые вам нужны. Есть документация и несколько примеров того, как оценить доверие к серверу.
У меня была такая же проблема, и, хотя добавление сертификата вручную устраняет проблему, это также означает необходимость обновлять приложение каждый раз, когда сертификат на сервере изменяется (например, когда он истекает, что, в моем случае, должно было произойти). в считанные дни).
Если вы используете IP-адрес для подключения к сокету, а сертификат предназначен для полного доменного имени (полное доменное имя, т.е. subdomain.example.com), тогда, когда операционная система проверяет сертификат, она будет проверять IP-адрес, к которому вы подключаетесь, сравните его с именем в сертификате и подумайте, что они разные, что приводит к сбою проверки цепочки.
Поэтому для всех, кто сталкивается с этой проблемой, я рекомендую использовать полное доменное имя во втором параметре для CFStreamCreatePairWithSocketToHost
а не IP-адрес. После этого он должен работать без включения сертификата в комплект и проверки вручную.