Я ломал голову над странной проблемой - чем-то, о чем, кажется, не говорят (или называют совсем по-другому). Удивительно, но я не могу найти пример HTTPS — все, что я нахожу, имеет это «задание»!
Вкратце:
Я пытаюсь создать «сервер», использующий TLS, используя действительный сертификат.
Проблема:
Как только я успешно импортирую сертификат, настрою настройки для GCDAsyncSockets, затем вызову startTLS, соединение немедленно прервется с «Ошибка SecureTransport -9800» — Chrome называет это «ERR_SSL_PROTOCOL_ERROR».
Тест:
- Запустить сервер.
- Подключитесь через Chrome или Safari (https://localhost или https://localhost:somefreeport).
- Попробуйте наблюдать за запросом страницы из полученных данных.
- Обратите внимание на сбой на этапе рукопожатия.
Я выбрал Chrome для тестирования, так как это упражнение позже будет обрабатывать трафик WebSocket, поэтому я использую действительный сертификат, а не самозаверяющий.
Длинное описание:
Используя GCDAsyncSocket для прослушивания порта, затем, как только я получаю соединение, я беру этот сокет и «startTLS» для его обработки. (Я не ограничиваюсь использованием GCDAsyncSocket, просто я знаком с ним в клиентском сокете, использую открытый текст и TLS, а также открытый текст сервера - только серверный TLS ставит меня в тупик).
Сертификат представляет собой подписанный сертификат с известным общедоступным центром сертификации (Comodo или GoDaddy). Я уже успешно использую его в .Net. Приведенный ниже источник успешно откроет сертификат и сообщит имя узла. .Net, однако, многое упрощает, поэтому сравнение не тривиально. (загрузить сертификат с пропуском в объект x509, затем применить к новому сокету. Принимая во внимание, что здесь я также должен определить шифры и версии SSL).
Упрощенный пример кода:
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
//Get certificate
NSString* p12Path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mySignedCert"
ofType:@"pfx"];
CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain([[NSData alloc] initWithContentsOfFile:p12Path]);
CFStringRef password = CFSTR("myCertPassword"); //Cert Password
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
CFRelease(options);
CFRelease(password);
if(securityError == errSecSuccess)
NSLog(@"Success opening p12 certificate."); //All good!
else
return nil;
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef myIdent = (SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);
SecIdentityRef certArray[1] = { myIdent };
CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
//Build TLS settings dictionary
[self willSecureWithSettings:settings]; //This just uses SSLGetNumberSupportedCiphers & SSLGetSupportedCiphers to create a cipher array and appends to settings
settings[(NSString *)kCFStreamSSLCertificates] = (__bridge id)(myCerts);
settings[(NSString *)kCFStreamSSLPeerName] = @"my.peer.address";
/* Valid values for protocol types
kSSLProtocolUnknown = 0, no protocol negotiated/specified; use default
kSSLProtocol3 = 2, SSL 3.0
kTLSProtocol1 = 4, TLS 1.0
kTLSProtocol11 = 7, TLS 1.1
kTLSProtocol12 = 8, TLS 1.2
kDTLSProtocol1 = 9, DTLS 1.0
*/
//Tried 0,2,4,7,8 - 9 throws another error, possibly unsupported.
settings[GCDAsyncSocketSSLProtocolVersionMin] = [NSNumber numberWithInteger:8];
settings[GCDAsyncSocketSSLProtocolVersionMax] = [NSNumber numberWithInteger:8];
[newSocket startTLS:settings];
[newSocket readDataWithTimeout:-1 tag:0];
}
Я нашел много старых примеров, ни один из них больше не применим (без использования более старого GCDAsyncSocket или более старого Xcode). Самое близкое, что я нашел, упоминает о более позднем «GCDAsyncSocketSSLProtocolVersionMin/Max», установленном на 2, который, например, не поддерживается в Chrome.
Кто-нибудь был успешным и готов поделиться некоторыми указателями?
С уважением, КФ.