阅读iOS上的证书问题 [英] Reading Certificates on iOS Problem

查看:299
本文介绍了阅读iOS上的证书问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从iOS中的各种网址读取证书。我的代码但是不能正常工作 - 数组应该返回我需要的信息总是返回 null



我缺少什么?

   - (void)findCertificate: (NSString *)url 
{
NSInputStream * input = [[NSInputStream inputStreamWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@https://store.writeitstudios.com]]]]

[input setDelegate:self];

[input scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

[input open];

NSLog(@Status:%i,[input streamStatus]);
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
NSLog(@handle Event:%i eventCode);

if(eventCode == NSStreamStatusOpen)
{
NSArray * certificates =(NSArray *)CFReadStreamCopyProperty((CFReadStreamRef)aStream,kCFStreamPropertySSLPeerCertificates);

NSLog(@Certs:%@,CFReadStreamCopyProperty((CFReadStreamRef)aStream,kCFStreamPropertySSLPeerCertificates)

if([certificates count]> 0){
SecCertificateRef certificate =(SecCertificateRef)[certificates objectAtIndex:0];
NSString * description =(NSString *)SecCertificateCopySubjectSummary(certificate);
NSData * data =(NSData *)SecCertificateCopyData(certificate);
NSLog(@说明:%@,description);
}
}
}

我泄漏记忆。

解决方案

让我解释一下您在这里做什么以及为什么会出错:


  1. 正在加载网址的内容 https://store.writeitstudios.com (即HTML)同步到 NSData (数据缓冲区)。请注意,您加载任何证书(技术上, NSURL 会在内部加载它们,但这个代码绝对不会将它们放入 NSData

  2. 您正在打开一个输入流,并将数据(一点HTML,没有证书! li>
  3. 您已实现 NSStream 的委托方法 stream:handleEvent:读取kCFStreamPropertySSLPeerCertificates属性。

  4. 您正在将空属性转换为 NSArray



  5. <

    使用 NSStream / CFStream 对于手头的任务不是必需的。绝对不需要先通过 NSURLConnection ,然后通过 NSStream



    要检索SSL服务器证书,请坚持使用简单的异步 NSURLConnection ,并使用其委托方法访问证书:

      //开始异步下载的方法

    - void)beginCertificateDownload:(NSURL *)url
    {
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    [连接开始];
    }

    // NSURLConnection委托方法

    - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
    {
    return [[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust];
    }

    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {
    //提取证书
    SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
    CFIndex count = SecTrustGetCertificateCount(trustRef);
    for(CFIndex i = 0; i SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef,i);
    CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef);
    NSLog(@%@,certSummary);

    //使用这里的证书做你想做的任何事情
    //不要忘记复制它们,如果你需要保持他们
    //超出这个方法的范围
    }

    //假设你对实际加载URL的内容不感兴趣,所以取消
    [[challenge sender] cancelAuthenticationChallenge:challenge];

    //你也想在某点释放连接对象
    }


    I am trying to read certificates from various URLs in iOS. My code however is not working well - the array that should return the information I need always returns null.

    What am I missing?

    - (void)findCertificate:(NSString *)url
    {
        NSInputStream*input = [[NSInputStream inputStreamWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://store.writeitstudios.com"]]] retain];
    
        [input setDelegate:self];
    
        [input scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
        [input open];
    
        NSLog(@"Status: %i",[input streamStatus]);
    }
    
    - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
    {
        NSLog(@"handle Event: %i",eventCode);
    
        if (eventCode == NSStreamStatusOpen)
        {
            NSArray *certificates = (NSArray*)CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates); 
    
            NSLog(@"Certs: %@",CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates));
    
            if ([certificates count] > 0) { 
                SecCertificateRef certificate = (SecCertificateRef)[certificates objectAtIndex:0]; 
                NSString *description = (NSString*)SecCertificateCopySubjectSummary(certificate); 
                NSData *data = (NSData *)SecCertificateCopyData(certificate); 
                NSLog(@"Description: %@",description);
            }
        }
    }
    

    And yes, I am aware that I am leaking memory. This is just a snippet.

    解决方案

    Let me explain what you're doing here and why it's wrong:

    1. You are loading the contents of the URL https://store.writeitstudios.com (i.e. the HTML) synchronously into an NSData (a data buffer). Note that you are not loading any certificates (well, technically NSURL will load them internally, but this code is most definitely not putting them into the NSData)
    2. You are opening an input stream and sticking the data (a bit of HTML, no certificates!) into it.
    3. You have implemented NSStream's delegate method stream:handleEvent: and are attempting to read the kCFStreamPropertySSLPeerCertificates property. This property will be empty since the stream contains only a bit of HTML data, nothing else.
    4. You are casting the empty property to an NSArray.
    5. The loop is not executed because the array is NULL.

    Using NSStream/CFStream is not necessary for the task at hand. And most definitely you don't have to go through NSURLConnection first and then through NSStream.

    To retrieve SSL server certificates, stick to a simple, asynchronous NSURLConnection and use its delegate methods to access the certificates:

    // Method to begin the asynchronous download
    
    - (void)beginCertificateDownload:(NSURL *)url
    {
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    
        [connection start];
    }
    
    // NSURLConnection Delegate Methods
    
    - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
    {
        return [[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {
        // extract the certificates
        SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
        CFIndex count = SecTrustGetCertificateCount(trustRef);
        for (CFIndex i = 0; i < count; i++) {
            SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, i);
            CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef); 
            NSLog(@"%@", certSummary);
    
            // do whatever you need with the certificates here
            // don't forget to copy them if you need to keep them
            // around beyond the scope of this method
        }
    
        // I'm assuming you're not interested in actually loading the contents of the URL, so cancel
        [[challenge sender] cancelAuthenticationChallenge:challenge];
    
        // you'll also want to release the connection object at some point
    }
    

    这篇关于阅读iOS上的证书问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆