首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有SSL / TLS支持的目标-C TCP服务器

带有SSL / TLS支持的目标-C TCP服务器
EN

Stack Overflow用户
提问于 2013-10-25 12:46:05
回答 2查看 5.2K关注 0票数 3

我有一个简单的TCP服务器/客户端设置。这种连接实际上非常有效。

现在,我想为套接字连接实现SSL / TLS加密。我使用密钥链访问创建了一个PKCS12证书。在我的服务器中,接受回调中有以下代码:

代码语言:javascript
运行
复制
NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"TCPServerCertificate" ofType:@"p12"];
NSData *certificateData = [NSData dataWithContentsOfFile:certificatePath];

CFArrayRef keyRef;
OSStatus status = SecPKCS12Import((__bridge CFDataRef)certificateData, (__bridge CFDictionaryRef)@{(__bridge NSString *)kSecImportExportPassphrase: @"1234"}, &keyRef);

if (status != noErr) {
    NSLog(@"PKCS12 import error %i", status);
    return;
}

CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyRef, 0);
SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);

SecCertificateRef certificate;
status = SecIdentityCopyCertificate(identityRef, &certificate);

if (status != noErr) {
    NSLog(@"sec identity copy failed: %i", status);
    return;
}

NSArray *certificates = [NSArray arrayWithObjects:(__bridge id)identityRef, (__bridge id)certificate, nil];

NSDictionary *settings = @{(NSString *)kCFStreamPropertyShouldCloseNativeSocket:    [NSNumber numberWithBool:YES],
                           (NSString *)kCFStreamSSLValidatesCertificateChain:       [NSNumber numberWithBool:YES],
                           (NSString *)kCFStreamSSLAllowsExpiredCertificates:       [NSNumber numberWithBool:NO],
                           (NSString *)kCFStreamSSLAllowsExpiredRoots:              [NSNumber numberWithBool:NO],
                           (NSString *)kCFStreamSSLAllowsAnyRoot:                   [NSNumber numberWithBool:YES],
                           (NSString *)kCFStreamSSLCertificates:                    certificates,
                           (NSString *)kCFStreamSSLIsServer:                        [NSNumber numberWithBool:YES],
                           (NSString *)kCFStreamSSLLevel:                           (NSString *)kCFStreamSocketSecurityLevelTLSv1};

CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);

然后创建流的NSStream实例,并在另一个类中处理它们。

当我运行服务器并连接一个客户端时,我将在我的委托中获得常规的NSStreamEventOpenCompleted。然后,当我尝试写到流或事件时,如果我刚刚关闭了连接,我将得到以下错误:

代码语言:javascript
运行
复制
2013-10-25 13:27:08.584 TCPServer[6435:303] CFNetwork SSLHandshake failed (-9800)
2013-10-25 13:27:08.584 TCPServer[6435:303] NSStreamEventOpenCompleted
2013-10-25 13:27:08.585 TCPServer[6435:303] NSStreamEventErrorOccurred

我想知道我必须在客户端实现什么。另外,我还想知道为什么在发送数据或断开与客户端的连接时会出现握手失败。每当发生此错误时,客户端都认为它仍然是连接的。

是否有任何好的TCP /TLS教程或其他材料同时涵盖客户端和服务器端?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-15 21:01:42

此代码存在一些问题:您不能用kCFStreamPropertyShouldCloseNativeSocket设置kCFStreamPropertySSLSettings,也不应该混合服务器和客户端代码。

对于服务器,只需设置一个证书即可。

代码语言:javascript
运行
复制
CFReadStreamSetProperty(read, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(write, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
//kCFStreamPropertySocketSecurityLevel
//Note: If you set this key, you must do so before setting any other SSL options, such as kCFStreamPropertySSLSettings.
CFReadStreamSetProperty(read, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);
CFWriteStreamSetProperty(write, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);
//Creating server dictionnary

//kCFStreamSSLIsServer
//If the value of this key is kCFBooleanTrue, the kCFStreamSSLCertificates key must contain a valid value

//kCFStreamSSLCertificates
//Security property key whose value is a CFArray of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef.
//For more information, see SSLSetCertificate() in Security/SecureTransport.h.

NSDictionary *settings = @{(id)kCFStreamSSLCertificates:                    certificates,
                           (id)kCFStreamSSLIsServer:                        @YES};


//Apply settings
CFReadStreamSetProperty(read, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)(settings));
CFWriteStreamSetProperty(write, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)(settings));

对于客户端,如果要覆盖验证链(参见Apple关于覆盖链验证的内容),应执行以下操作:

代码语言:javascript
运行
复制
CFReadStreamSetProperty(read, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(write, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
//kCFStreamPropertySocketSecurityLevel
//Note: If you set this key, you must do so before setting any other SSL options, such as kCFStreamPropertySSLSettings.

CFReadStreamSetProperty(read, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);
CFWriteStreamSetProperty(write, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);

//DO NOT USE kCFStreamPropertySSLContext as it overrides the following configuration
//create dictionnary for kCFStreamPropertySSLSettings

//keys for dictionnary we want to change:kCFStreamSSLAllowsExpiredCertificates;kCFStreamSSLAllowsExpiredRoots;kCFStreamSSLAllowsAnyRoot;
//kCFStreamSSLValidatesCertificateChain => no need to worry about the root
//kCFStreamSSLPeerName kCFNull prevents name verification


settings = @{(id)kCFStreamSSLValidatesCertificateChain: @NO,//The delegate will verify this
             (id)kCFStreamSSLPeerName: (id)kCFNull};//prevents name verification if server is not fixed (eg. IP)

//Apply settings
CFReadStreamSetProperty(read, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)(settings));
CFWriteStreamSetProperty(write, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)(settings));
票数 1
EN

Stack Overflow用户

发布于 2020-04-30 17:57:25

我刚刚创建了一个包,使用新的iOS 13限制使TLS/TCP更容易。希望它能帮到别人!请随时作出贡献:

https://github.com/eamonwhiter73/IOSObjCWebSockets

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19590279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档