【问题标题】:SSL Identity Certificate to run an HTTPS Server on iOS在 iOS 上运行 HTTPS 服务器的 SSL 身份证书
【发布时间】:2012-04-10 02:56:01
【问题描述】:

我正在尝试在 iOS 应用中构建 HTTPS 服务器,以充当我的网络应用和外部服务器之间的代理。

感谢 CFSocketRef 或使用 GCDAsyncSocket 库,我已经设法通过侦听套接字来创建 HTTP 服务器。 我还成功地使用 GCDAsyncSocket 库制作了一个运行 HTTPS 服务器的 Mac 应用程序,这要归功于我的方法“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];
}

我使用的证书是我使用 Keychain Access 创建的自签名服务器 SSL 证书。 所以我知道我必须给系统一个配置集,其中包含一个包含身份和证书的数组。它在我的 Mac 应用上运行良好。

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

如何在 iOS 上创建 SecIdentityRef(启用 SSL 服务器端)?我是否错过了,例如将公钥/私钥存储在我的应用中,或者其他什么?非常感谢。

【问题讨论】:

  • 在 CocoaAsyncSocket v7.4 中进行了更改,一些旧的选项键现在不可用并且会抛出异常。使用 GCDAsyncSocketManuallyEvaluateTrust 并在 -socket:didReceiveTrust: 委托中进行评估。在gist.github.com/hlung/6432966 中查看我的示例

标签: ios networking ssl https


【解决方案1】:

我将发布一个单独的答案,因为 cmets 不适合代码共享。
这是我用来导入我的 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 内容将在 keystore 数组中。

【讨论】:

  • 我的代码在这里使用 ARC,因此需要神秘的 __bridge 关键字;)
  • 我也在做同样的事情。我得到与您的代码相同的结果: keystore 数组为空。如果您使用相同的代码有更好的结果,我想这意味着我没有生成或存储我的证书,对吧?我所做的是从 Keychain Access 创建一个自签名根证书,然后我将 .cer 和 .p12 文件存储在我的项目包中,我尝试使用它们但没有成功,如您所见。感谢您的宝贵时间,感谢您的帮助。
  • 只是为了让它工作......你为什么不尝试导出一些你的工作密钥/证书对(例如由 Apple 签署的开发证书)。
  • 我已经尝试使用有效的证书并且它有效。我还有一个问题,但感谢您的帮助!
【解决方案2】:

【讨论】:

  • 我实际上已经尝试过了,但我无法让它工作——这可能是正确的问题。我已经导入了我的私钥(p12 文件)并使用了 Apple 在您的链接中显示的 extractIdentityAndTrust() 函数,但我总是得到一个空的 items 数组,这使得该函数在尝试访问数组的第一个元素。有什么想法吗?
  • 如果您使用了 'SecPKCS12Import' 方法,它将返回一个包含 NSDictionaries 的 NSArray。字典中的身份存储在密钥“kSecImportItemIdentity”下,而证书链(同样是 NSArray)存储在密钥“kSecImportItemCertChain”下。与此同时,我也在寻找一种在运行时创建身份的方法,因为我不处理预加载的证书。如果我发现了什么,将在此处发布结果;)
  • 谢谢@pmilosev。我的问题是我使用了 Apple 在上面的链接中显示的函数 extractIdentityAndTrust 但是我得到的数组 items 总是空的:NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"myPrivateKeyPassword" forKey:(id)kSecImportExportPassphrase]; CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2019-01-12
  • 2021-12-16
  • 1970-01-01
相关资源
最近更新 更多