简体   繁体   English

如何在我的iOS应用程序中使用CFStream将客户端SSL证书发送到服务器?

[英]How to send a client SSL certificate to server by using CFStream in my iOS app?

We have a WebSocket security server working on SSL. 我们有一个处理SSL的WebSocket安全服务器。 We hope to put a client SSL certificate in our iOS client, in order to ensure the security when communicating with server. 我们希望在我们的iOS客户端中放置客户端SSL证书,以确保与服务器通信时的安全性。

Because we are using WebSocket, in iOS client, we use SocketRocket (Objective-C WebSocket client library) to implement WebSocket communication. 因为我们正在使用WebSocket,所以在iOS客户端中,我们使用SocketRocket (Objective-C WebSocket客户端库)来实现WebSocket通信。

The problem is I have no idea on how to send my client SSL certificate to server. 问题是我不知道如何将我的客户端SSL证书发送到服务器。

I can set the properties of CFStream, like kCFStreamPropertySocketSecurityLevel . 我可以设置CFStream的属性,如kCFStreamPropertySocketSecurityLevel But I don't know how it works. 但我不知道它是如何工作的。 And I can't find any docs about certificate in CFStream. 我在CFStream中找不到任何关于证书的文档。

I know that when we need to connect to a HTTPS server, we can use didReceiveAuthenticationChallenge in NSURLConnection. 我知道,当我们需要连接到一个HTTPS服务器,我们可以使用didReceiveAuthenticationChallenge在NSURLConnection的。 But And as I know, there wasn't a counterpart in CFStream. 但据我所知,CFStream中没有对应物。

Could someone have any ideas? 有人有什么想法吗?

After a lot of study and trying, I can answer myself now. 经过大量的学习和尝试,我现在可以自己回答。 Also hope it'll be useful for you. 也希望它对你有用。

Actually, what I need is implementing client SSL authentication by using CFStream. 实际上,我需要的是使用CFStream实现客户端SSL身份验证。 So I need to do these: 所以我需要这样做:

  1. Put PKCS #12 file in my app bundle 将PKCS#12文件放入我的应用包中
  2. Read this file as NSData to pkcsData 将此文件作为NSData读取到pkcsData
  3. Use method SecPKCS12Import to import pkcsData 使用方法SecPKCS12Import导入pkcsData
  4. Get identity and cert from the data you imported above, and generate a certificates array 从上面导入的数据中获取身份和证书,并生成证书数组
  5. Set the array to key kCFStreamSSLCertificates in kCFStreamPropertySSLSettings of your CFWriteStreamRef 设置阵列关键kCFStreamSSLCertificateskCFStreamPropertySSLSettings您的CFWriteStreamRef

Sample code below: 示例代码如下:

  // Read .p12 file
  NSString *path = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
  NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:path];

  // Import .p12 data
  CFArrayRef keyref = NULL;
  OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)pkcs12data,
                                         (__bridge CFDictionaryRef)[NSDictionary
                                                                    dictionaryWithObject:@"123456"
                                                                    forKey:(__bridge id)kSecImportExportPassphrase],
                                         &keyref);
  if (sanityChesk != noErr) {
    NSLog(@"Error while importing pkcs12 [%ld]", sanityChesk);
  } else
    NSLog(@"Success opening p12 certificate.");

  // Identity
  CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
  SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                                                    kSecImportItemIdentity);

  // Cert
  SecCertificateRef cert = NULL;
  OSStatus status = SecIdentityCopyCertificate(identityRef, &cert);
  if (status)
    NSLog(@"SecIdentityCopyCertificate failed.");

  // the certificates array, containing the identity then the root certificate
  NSArray *myCerts = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, (__bridge id)cert, nil];

  //
  [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
  [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
  [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
  [SSLOptions setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
  [SSLOptions setObject:@"test.domain.com:443" forKey:(NSString *)kCFStreamSSLPeerName];
  [SSLOptions setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel];
  [SSLOptions setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamPropertySocketSecurityLevel];
  [SSLOptions setObject:myCerts forKey:(NSString *)kCFStreamSSLCertificates];
  [SSLOptions setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLIsServer];

  [_outputStream setProperty:SSLOptions
                        forKey:(__bridge id)kCFStreamPropertySSLSettings];

Because I use SocketRocket, I've added these code in my own fork: https://github.com/nickcheng/SocketRocket 因为我使用SocketRocket,所以我在自己的fork中添加了这些代码: https//github.com/nickcheng/SocketRocket

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在iOS上使用CFStream套接字接受不受信任的SSL服务器证书 - Accept untrusted SSL server certificate with CFStream socket on iOS 在企业 iOS 应用程序中使用来自 .mobileconfig 的客户端 SSL 证书 - Using Client SSL Certificate from .mobileconfig within Enterprise iOS app 使用SSL证书将iOS应用与Apache Server连接? - Connect iOS app with Apache Server using SSL certificate? 如何在iOS中使用CFStream连接到公共IP - How to connect to public ip using CFStream in iOS 如何在iOS中检索ssl服务器证书? - How to retrieve the ssl server certificate in iOS? 我的iOS通知服务器正在使用DEV SSL证书,但正在连接gateway.push.apple.com? - My iOS notification server is using DEV SSL Certificate but is connecting to gateway.push.apple.com? 如何将 iOS 应用程序发送到客户端 - How to send iOS app to a client 在IOS 7.0中,CFStream套接字发送数据包未完成 - CFStream Socket send packet not complete in IOS 7.0 如何在iOS App中使用客户端证书身份验证 - How to use Client Certificate Authentication in iOS App 在我的ios应用中使用NSUrl将加密的数据发送到服务器 - Using NSUrl in my ios app send data encrypted to the server
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM