阅读iOS问题证书

Pri*_*yat 3 iphone certificate objective-c

我正在尝试从iOS中的各种URL读取证书.然而,我的代码运行不正常 - 应该返回我需要的信息的数组总是返回null.

我错过了什么?

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

是的,我知道我在泄漏记忆.这只是一个片段.

puz*_*zle 9

让我解释一下你在这里做什么以及为什么这是错误的:

  1. 您正在将URL https://store.writeitstudios.com(即HTML)的内容同步加载到NSData(数据缓冲区)中.请注意,您没有加载任何证书(好吧,技术上NSURL会在内部加载它们,但是这段代码绝对不会将它们放入其中NSData)
  2. 您正在打开输入流并将数据(一些HTML,没有证书!)粘贴到其中.
  3. 您已实现了NSStream委托方法,stream:handleEvent:并且正在尝试读取kCFStreamPropertySSLPeerCertificates属性.此属性将为空,因为流只包含一些HTML数据,没有别的.
  4. 您正在将空属性转换为NSArray.
  5. 由于数组是,因此不执行循环NULL.

使用NSStream/ CFStream不是手头的任务所必需的.而且绝大多数你绝对不需要先经过NSURLConnection然后经过NSStream.

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

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