首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么CFStream不使用TLS1.3?

为什么CFStream不使用TLS1.3?
EN

Stack Overflow用户
提问于 2020-10-11 04:44:04
回答 1查看 245关注 0票数 3

我试图弄清楚为什么运行iPhone 14的iOS不使用TLS1.3连接到兼容的web服务器。

有关守则是:

代码语言:javascript
复制
- (void) streamOpened:(NSStream *)stream {
    NSDictionary *settings = @{
                               (__bridge NSString *)kCFStreamSSLValidatesCertificateChain: (__bridge NSNumber *)kCFBooleanFalse
                               };
    CFReadStreamSetProperty((CFReadStreamRef)inputStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
    CFWriteStreamSetProperty((CFWriteStreamRef)outputStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
}

完整的源代码可以在这里看到:https://github.com/tls-inspector/tls-inspector/blob/app-store/CertificateKit/Getters/CKAppleCertificateChainGetter.m

我曾经尝试指定kCFStreamSSLLevel设置为kCFStreamSocketSecurityLevelTLSv1_3的SSL级别,但这没有起到任何作用。

如果我使用OpenSSL进行连接,它使用TLS1.3,我可以通过数据包捕获来验证这一点,但是使用CFStream,它将保持在1.2。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-16 16:22:23

简单的回答是,您最终使用的是不支持TLS1.3的不推荐API。

下面给出了详细说明潜在解决方案的详细答案。

我试图用CFStream解决这个问题,但没有成功。

这可能是可能的。问题是,您最终会像使用SSLConnectionRef和朋友一样,在较低的级别使用NSInputStreamNSOutputStream以及朋友,而在更高的级别上,您会遇到这个https://developer.apple.com/documentation/security/secure_transport?language=objc遗留API。

在那一页上,它提到了API被网络框架所取代,实际上这就是我建议您应该使用的内容。我希望也能快速地实现一个解决方案,但它需要更多的返工,所以我把它放在这里。

不过,谨此提出一些建议,基本上是我希望落实的想法。

和以前一样,有两个层次。

在较低的级别,您最终使用的是nw_和家庭,但我要说的是,不要这样做。它可能需要一些专门的需求,您的应用程序可能在这一类别,但仍然要注意,更高的层次是建立在此之上。

在更高的层次上,这就是我认为您的解决方案所在,您最终使用的是NSURL和朋友。这里的goto可能是NSURLSession,但是实现将决定这一点。我试图给出一个大纲,您可以查看我的代码,以获得更多的细节,但我认为从现在开始,您将能够更好地实现。

在这方面,我希望将遗留的流代码连接到NSURLSession,但当失败时,我停止了。这可能有点乐观,我认为这需要更严肃的重做,但各种代表(NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionStreamDelegate等)似乎已经准备好等待您的解决方案,我不认为这实际上是很多工作。

下面是我的尝试中最相关的代码片段。这打开了TLS1.3,我试着实现它。

代码语言:javascript
复制
    // Some configuration
    NSURLSessionConfiguration * config = NSURLSessionConfiguration.ephemeralSessionConfiguration;

    // Note this one!!!
    config.TLSMaximumSupportedProtocol = kTLSProtocolMaxSupported;
        
    NSURLSession * urlSession = [NSURLSession sessionWithConfiguration:config
                                  delegate:self
                                 delegateQueue:NSOperationQueue.currentQueue];

从这一点开始,我尝试重用您的流代码,但老实说,我认为最终的解决方案甚至可能不再使用流,而只是依赖于使用正确的委托。请原谅我对此感到兴奋,但我怀疑您将因此能够大大简化您的代码。

我很喜欢你的应用程序-它是相当完美的,我期待你解决这个问题。我也喜欢玩它,但现在这是我的贡献。

第一次尝试

我看了你的代码-它需要一些重新工作的TLS 1.3。我试着去做,但是现在我正在重写那堂课,所以我停下来了。你能做到的,但是,我不能保证它会起作用!

总之,这里有一些想法。

首先讨论现有的代码。只是一些-嗯-观察,没什么大不了的.

请注意,无论触发哪个流,streamOpened都将应用这些设置。委托将向我传递两次信息,一次用于输入,一次用于输出流。虽然这里看起来并不重要,但您应该小心,因为这可能会在另一种情况下引入一些严重的bug。

另外,我认为您需要在流打开之前配置它们,但这并没有造成任何不同。如果在performTaskForURL中打开流之前或之后在streamOpened中对它们进行配置,这并不重要。

我玩了一下配置。您不需要在输出流上设置一个,只需要在输入上设置一个。唯一需要的键是你已经设置的钥匙。不管我做了什么,我都无法得到任何不同。

其次,我认为的解决方案在这里是可行的。

您需要配置URL会话。所以我所做的是

代码语言:javascript
复制
- (void) performTaskForURL:(NSURL *)url{

    queryURL = url;

    // Some configuration
    NSURLSessionConfiguration * config = NSURLSessionConfiguration.ephemeralSessionConfiguration;

    // Note this one!!!
    config.TLSMaximumSupportedProtocol = kTLSProtocolMaxSupported;
        
    NSURLSession * urlSession = [NSURLSession sessionWithConfiguration:config
                                  delegate:self
                                 delegateQueue:NSOperationQueue.currentQueue];

    // Just code to test the idea, not production ready I know
    NSURLSessionStreamTask * streamTask = [urlSession streamTaskWithHostName:url.host
                                        port:443];
    [streamTask captureStreams];
}

- (void)URLSession:(NSURLSession *)session
    streamTask:(NSURLSessionStreamTask *)streamTask
didBecomeInputStream:(NSInputStream *)inputStreamUrl
      outputStream:(NSOutputStream *)outputStreamUrl
{
    // I was hoping to get away with this,
    // just setting your streams equal to the
    // URL stream task streams but it did not
    // work ... problem is you need more of the
    // stream task delegate methods I believe
    inputStream = inputStreamUrl;
    outputStream = outputStreamUrl;

    // This is some left over code from your performTaskForURL message
    // Here you can see how I toyed with the stream configuration

    // Configure here before it is opened
    // Pretty much your current streamOpened message
    // Note only input needs be configured (fwiw)
    [self configureStream:inputStream];

    inputStream.delegate = self;
    outputStream.delegate = self;

    [outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    [outputStream open];
    [inputStream open];

    // I was hoping this would just work but I think it needs more work
}

这里的想法是使用kTLSProtocolMaxSupported配置一个URL会话,然后创建一个流任务。这就是我想要停下来的地方,我认为你更擅长于更进一步。我希望我能得到流并将它们扔回您的代码中,但是它没有工作,目前我没有更进一步。

我无法测试我的想法,因为我需要将更多的东西与您的类现在也实现的NSURLSessionStreamDelegate连接起来。我认为你已经在课堂上做了同样的事情,但是对于流来说。

现在,我可能又错了,我想在发布之前进行测试,但要么看看这是否可行,然后我认为您需要实现委托方法,例如URLSession:task:didReceiveChallenge:completionHandler:

我认为您已经在代码中做了类似的事情,但这就是为什么我要在这里停下来,因为我认为您会更好地判断这个想法。

我已经尝试了更多,但没有成功--但我认为您需要在这里使用NSURLSession,甚至可以代替套接字。

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

https://stackoverflow.com/questions/64300673

复制
相关文章

相似问题

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