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-адрес. После этого он должен работать без включения сертификата в комплект и проверки вручную.

Другие вопросы по тегам