Как установить SSL-шифры при использовании CFSocket/CFStream в Какао?
Недавно мне нужно было настроить CocoaHttpServer, который мы успешно используем в нашем приложении, для обработки HTTPS-соединений, исходящих из клиентского приложения (работающего на устройствах Android). Это хорошо - есть обильный пример кода, который позволяет это сделать, и мы смогли включить безопасный сервер без проблем.
На практике мы наблюдали невероятно длительные фазы согласования SSL, пока клиент выполнял рукопожатие с нашим сервером - свыше 70 секунд.
В ходе долгих поисков я обнаружил, что задержка вызвана вычислением параметров Диффи-Хеллмана, используемых по умолчанию, когда SSL включен в CFSocket. В этой теме я впервые начал искать ответ на свой вопрос.
Чтобы соответствовать тому, что делал наш сервер Windows (используя менее защищенный шифр SSL), мне нужно было явно установить шифр на Mac, что нелегко при использовании AsyncSocket в качестве оболочки для обмена сокетами.
Наш сервер Windows использовал: TLS_RSA_WITH_RC4_128_MD5)(0x04) RC4 128 бит MD5 RSA
Наш сервер Macintosh использовал: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x039) AES 256 бит SHA-1 Обмен эфемерным ключом Диффи-Хеллмана с использованием сертификата RSA
Разница в "безопасности" велика, но, вероятно, не стоит того усилия / вычисления / задержки, которые мы наблюдали. Театр безопасности?
2 ответа
Обратите внимание, что есть разные шифры, которые можно выбрать - я решил использовать тот же, что и наша реализация Windows для согласованности.
С информацией из другого вопроса, упомянутого выше, я выяснил, как настроить шифр для CFSocket, чтобы он использовался так же, как Windows, и код теперь выглядит немного лучше - как будто он действительно работает! CFSocket напрямую не раскрывает поддержку SecureTransport, что усложняет этот вид, но определение конкретного ключа делает его работоспособным.
Для потомков вот код, который я добавил в -onSocketWillConnect: в нашем классе HTTPConnection:
// define this value; it isn't exposed by CFSocketStream.h
const extern CFStringRef kCFStreamPropertySocketSSLContext;
...
CFReadStreamRef stream = [sock getCFReadStream];
CFDataRef data = (CFDataRef) CFReadStreamCopyProperty(stream, kCFStreamPropertySocketSSLContext);
// Extract the SSLContextRef from the CFData
SSLContextRef sslContext;
CFDataGetBytes(data, CFRangeMake(0, sizeof(SSLContextRef)), (UInt8*)&sslContext);
SSLCipherSuite *ciphers = (SSLCipherSuite *)malloc(1 * sizeof(SSLCipherSuite));
ciphers[0] = SSL_RSA_WITH_RC4_128_MD5; // Basic cipher - not Diffie-Hellman
SSLSetEnabledCiphers(sslContext, ciphers, 1);
Я надеюсь, что это поможет любому, кто решает ту же проблему, что и я, - я был бы рад поделиться с вами еще несколькими кодами и советами, если это необходимо.
Что бы это ни стоило, я добавил патч для CocoaAsyncSocket примерно за неделю до появления этой проблемы. Извините, что тогда я не заметил ваш вопрос.:-)