在Cocoa中使用CFSocket/CFStream时如何设置SSL密码?

Bri*_*olo 8 sockets encryption ssl https objective-c

我最近需要配置CocoaHttpServer,我们在我们的应用程序中成功使用它来处理来自客户端应用程序(在Android设备上运行)的HTTPS连接.这很好 - 有大量的示例代码可以实现这一点,我们能够毫无问题地启用安全服务器.

在实践中,我们看到了令人难以置信的长SSL谈判阶段,而客户端正在与我们的服务器进行握手 - 超过70秒.

通过一系列的搜索,我发现延迟是因为在CFSocket中启用SSL时默认使用的Diffie-Hellman参数的计算.这个帖子是我第一次找到问题答案的地方.

为了匹配我们的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证书进行短暂的Diffie-Hellman密钥交换

"安全性"的差异很大,但可能不值得我们看到的努力/计算/延迟.安全剧院?

Bri*_*olo 4

请注意,可以选择不同的密码 - 为了保持一致性,我选择使用与 Windows 实现相同的密码。

根据上面提到的另一个问题的信息,我弄清楚了如何设置 CFSocket 的密码以使用与 Windows 相同的密码,并且代码现在看起来好多了 - 就像它真的有效一样!CFSocket 并不直接公开 SecureTransport 支持,这使得这种方式变得困难,但定义一个特定的密钥可以使其很好地工作。

为了方便后代,以下是我添加到 HTTPConnection 类中 -onSocketWillConnect: 的代码:

// define this value; it isn't exposed by CFSocketStream.h
const extern CFStringRef kCFStreamPropertySocketSSLContext;
Run Code Online (Sandbox Code Playgroud)

...

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);
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助任何人解决与我相同的问题 - 如果需要,我很乐意分享更多代码和建议。