2012-03-26 110 views
6

我试图在iOS应用中构建HTTPS服务器,以充当我的web-app和我的外部服务器之间的代理。SSL身份证书在iOS上运行HTTPS服务器

我设法通过侦听套接字来创建一个HTTP服务器,这要归功于CFSocketRef或使用GCDAsyncSocket库。 我也有成功做出Mac应用程序运行的HTTPS服务器,使用GCDAsyncSocket库,并感谢我的方法“的SecureSocket:”低于固定连接:

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 
{ 
    // (...) 
    // secure the connection 
    [self secureSocket:newSocket]; 
    // (...) 
} 

- (void)secureSocket:(GCDAsyncSocket *)sock 
{ 
    // The root self-signed certificate I have created 
    NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; 
    NSData *certData = [[NSData alloc] initWithContentsOfFile:certificatePath]; 
    CFDataRef certDataRef = (CFDataRef)certData; 
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); 
    [certData release]; 

    // the "identity" certificate 
    SecIdentityRef identityRef; 
    SecIdentityCreateWithCertificate(NULL, cert, &identityRef); 

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

    // the SSL configuration 
    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3]; 
    [settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 
    [settings setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 
    [settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel]; 
    [settings setObject:certs forKey:(NSString *)kCFStreamSSLCertificates]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLIsServer]; 

    [sock startTLS:settings]; 
    [certs release]; 
} 

我使用的证书是自签署的服务器SSL证书,我已使用Keychain Access创建。 所以我明白我必须给系统配置一个包含身份和证书的数组。它可以在我的Mac应用程序中正常工作。

问题是在我的iOS应用程序的HTTP服务器上启用SSL。 创建身份的方法“SecIdentityCreateWithCertificate()”在iOS上不存在,我不知道如何以另一种方式创建身份。

如何在iOS上创建SecIdentityRef(启用SSL服务器端)?我是否错过喜欢将公钥/私钥存储在我的应用程序或其他内容中?非常感谢。

+0

它已经在CocoaAsyncSocket v7.4中改变了,一些旧的选项键现在不可用并且会抛出异常。相反,使用GCDAsyncSocketManuallyEvaluateTrust并在-socket:didReceiveTrust:delegate中进行评估。在https://gist.github.com/hlung/6432966 – Hlung 2014-07-04 10:16:45

回答

4

我会发布一个单独的答案,因为评论不适合代码共享。
以下是我用来导入我的PKCS12:

CFArrayRef keyref = NULL; 
OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)p12Data, 
             (__bridge CFDictionaryRef)[NSDictionary 
                    dictionaryWithObject:password 
                    forKey:(__bridge id)kSecImportExportPassphrase], 
             &keyref); 

if (sanityChesk != noErr) { 
    NSLog(@"Error while importing pkcs12 [%d]", sanityChesk); 
    return nil; 
} 

NSArray *keystore = (__bridge_transfer NSArray *)keyref; 

完整的P12内容将是密钥库阵列英寸

+0

我的代码在这里使用ARC,因此需要隐含的__bridge关键字;) – pmilosev 2012-05-02 15:25:33

+0

我也是这样做的。我的代码得到了相同的结果:_keystore_数组为空。 如果您使用相同的代码获得更好的结果,我想这意味着我不会生成或存储我的证书吗?我所做的是从Keychain Access创建一个自签名的根证书,然后我将两个.cer和.p12文件存储在我的项目包中,我尝试使用它们,但没有成功。谢谢你的时间,我感谢你的帮助。 – Laurent 2012-05-08 11:35:35

+0

只是为了得到它的工作......为什么不尝试导出一些你的工作密钥/证书对(例如由苹果签署的开发证书)。 – pmilosev 2012-05-10 13:59:52

0
+0

中查看我的示例实际上,我已经尝试过,但无法使其工作 - 这可能是正确的问题。我已经导入了我的私钥(p12文件),并在链接中使用了Apple所示的extractIdentityAndTrust()函数,但我总是会得到一个空的_items_数组,该函数在尝试访问数组的第一个元素时崩溃。任何想法呢? – Laurent 2012-03-28 10:41:07

+0

如果您使用'SecPKCS12Import'方法,它将返回一个包含NSDictionaries的NSArray。字典中的标识存储在密钥'kSecImportItemIdentIdentity'下,而证书链(NSArray再次)存储在密钥'kSecImportItemCertChain'下。同时我也在寻找一种在运行时创建身份的方法,因为我没有处理预加载的证书。如果我发现某些内容,将在此发布结果;) – pmilosev 2012-04-04 15:56:51

+0

谢谢@pmilosev。我的问题是,我使用函数_extractIdentityAndTrust_如上面链接中的Apple所示,但是我得到的数组_items_总是空的: 'NSDictionary * optionsDictionary = [NSDictionary dictionaryWithObject:@“myPrivateKeyPassword”forKey:(id)kSecImportExportPassphrase]; CFArrayRef items = CFArrayCreate(NULL,0,0,NULL); securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);' – Laurent 2012-05-01 14:46:43

相关问题