在iOS上接受带有CFStream套接字的不受信任的SSL服务器证书

时间:2012-03-08 14:07:35

标签: iphone ios security ssl

我需要打开一个CFStream套接字连接到具有不受信任的CA根的服务器。我有服务器的证书,我可以从中创建一个SecCertificateRef结构。问题是如何设置流的属性。

我认为我应该将kCFStreamPropertySSLSettings属性设置为CFDictionary,而kCFStreamSSLCertificates又包含SecCertificateRef密钥。根据文档,这个键应该包含一个“SecCertificateRefs的CFArray,除了数组中的第一个元素,它是一个SecIdentityRef”。现在,我可以从我随应用程序提供的服务器证书中创建SecIdentityRef,但是如何获取{{1}}?我想它应该是客户端身份,但我现在绝对不想要客户端身份验证。而且我找不到如何仅使用服务器证书来提供CFStream的方法。

注意,我不想将不受信任的证书添加到钥匙串,也不要在设置中禁用kCFStreamSSLValidatesCertificateChain。我需要接受服务器身份验证,只要它是基于我自己从磁盘加载的服务器证书数据,并且只在此CFStream上。

2 个答案:

答案 0 :(得分:3)

我没有直接回答你的问题,但可能很少有指导原则:

  1. 为什么需要使用CFStream API而不是更直观的 NSURLConnection ? 从我在文档中可以找到的内容来看,它并不像Mac OS X中可用的所有关于CFStream API的内容都适用于iOS。所以想一想,看看你是否可以切换到NSURLConnection: - )

  2. 对于NSURLConnection,您可以使用 NSURLConnectionDelegate 方法获取SSL质询并自行验证证书。您可以查看我已实现这些功能的 wsdl2objc 项目:

  3. 现在关于你的问题:-)
    我不知道如何在 kCFStreamPropertySSLSettings 中设置自定义(不受信任)的CA.我不确定是否可以使用 kCFStreamSSLCertificates 来完成,因为它用于设置客户端证书(因此要求具有索引0上的 SecIdentityRef ,基本上提供了私钥。)

  4. 当您说您不想将证书添加到钥匙串时,您的意思是手动还是编程?我想您不希望您的应用的用户必须手动执行此操作,但您可以使用 安全API 以编程方式导入证书。在这种情况下,您的证书将导入沙盒钥匙串,该钥匙串仅适用于您的应用程序。 (再次,不确定这是否有效,但值得尝试)

  5. 在我的应用程序中,我使用NSURLConnectionDelegate手动验证不受信任的证书。

    的问候,
    PECE

答案 1 :(得分:3)

基本上你必须:

  1. 使用kCFStreamSSLValidatesCertificateChain
  2. 禁用默认信任评估
  3. 获得信任对象(kCFStreamPropertySSLPeerTrust)一旦连接到流(但在发送任何数据之前,即在kCFStreamEventCanAcceptByteskCFStreamEventHasBytesAvailable事件上)
  4. 将您的自签名根证书设置为该信任对象的可信锚
  5. 可选地,您可以向信任对象添加自定义SSL策略(例如,主机名与证书CN不匹配),但是如果您这样做,那么在设置可信锚之前执行此操作很重要,或者您可能获得{{1结果
  6. 评估信任对象(kSecTrustResultRecoverableTrustFailure)并检查结果是SecTrustEvaluate还是kSecTrustResultProceed