【发布时间】:2015-08-27 19:55:12
【问题描述】:
这个问题试图为我的特定用例找到解决方案,并记录我为遵循此过程的其他人所做的尝试。
我们有一个 RESTful 服务器和一个 iOS 应用程序。我们有自己的证书颁发机构,服务器有根证书颁发机构和自签名证书。我们按照这个过程生成了以下文件:
http://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/
rootCA.pem 根CA.key 服务器.crt server.key
只有服务器证书存储在我们的服务器上,作为 SSL 过程的一部分,公钥与 API 调用一起发送以进行验证。
我已按照此流程使用 AFNetworking 来使用证书固定和公钥固定来验证我们的自签名证书:
http://initwithfunk.com/blog/2014/03/12/afnetworking-ssl-pinning-with-self-signed-certificates/
我们根据本指南将 .crt 文件转换为 .cer 文件(DER 格式):
并将 .cer 文件 (server.cer) 包含在 iOS 应用程序包中。这成功地允许我们的应用程序向我们的服务器发出 GET/POST 请求。但是,由于我们的服务器证书可能会过期或重新颁发,因此我们希望使用根 CA,就像 AFNetworking 上的此线程中的人们所做的那样:
https://github.com/AFNetworking/AFNetworking/issues/1944
目前我们已经更新到 AFNetworking 2.6.0,所以我们的网络库肯定应该包含所有更新,包括在这个讨论中的更新:
https://github.com/AFNetworking/AFNetworking/issues/2744
用于创建我们的安全策略的代码:
var manager: AFHTTPRequestOperationManager = AFHTTPRequestOperationManager()
manager.requestSerializer = AFJSONRequestSerializer() // force serializer to use JSON encoding
let policy: AFSecurityPolicy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.PublicKey)
var data: [NSData] = [NSData]()
for name: String in ["rootCA", "server"] {
let path: String? = NSBundle.mainBundle().pathForResource(name, ofType: "cer")
let keyData: NSData = NSData(contentsOfFile: path!)!
data.append(keyData)
}
policy.pinnedCertificates = data
policy.allowInvalidCertificates = true
policy.validatesDomainName = false
manager.securityPolicy = policy
包含 server.cer 后,我们可以通过固定公钥来信任我们的服务器(也尝试过 AFSecurityPolicyPinningMode.Certificate);这很有效,因为包含了确切的证书。但是,因为我们可能会更改服务器拥有的 server.crt 文件,所以我们希望能够仅使用 rootCA.cer 来完成。
但是,只有 rootCA 包含在应用程序包中,这似乎不起作用。是不是 rootCA 没有足够的关于公钥的信息来验证用根 CA 签名的服务器证书? server.crt 文件的 CommonName 也可能会发生变化。
另外,由于我对 SSL 术语的流利程度非常原始,如果有人能澄清我是否提出了正确的问题,那就太好了。具体问题是:
- 我是否正确生成了证书,以便服务器可以使用自签名的 server.crt 文件证明其身份?
- 是否可以仅将 rootCA.cer 文件包含到捆绑包中并能够验证叶证书 server.crt?它是否能够验证由同一个 rootCA 签名的另一个 server2.crt 文件?或者我们应该在 rootCA 和叶子之间包含一个中间证书?
- 公钥固定或证书固定是解决此问题的正确方法吗?我读过的每个论坛和博客文章都说是的,但即使使用最新的 AFNetworking 库,我们也没有任何运气。
- 服务器是否需要以某种方式同时发送 server.crt 和 roomCA.pem 签名?
【问题讨论】:
-
您是使用 Xcode7/iOS9 还是使用 Xcode6/iOS8 构建应用程序?如果是前者,请注意连接到服务器的规则现在更加严格,如果 SSL 密码套件被认为不够强大,连接会在系统级别被丢弃。它被称为 ATS(应用程序传输安全),您可以在 developer.apple.com/library/prerelease/ios/technotes/… 找到更多信息
-
@jcayzac,目前正在尝试使其适用于 xcode 6/ios8。我们还没有对 ios9 做太多事情。是否建议只切换到通过 ios9 实现事物?即使我们的用户群没有更新,它还能工作吗?
-
我的建议是永远不要使用 AFNetworking...但这只是我的建议
-
有更好的选择吗?似乎 AFNetworking 是一个被广泛接受的库,并且维护得很好。可能比我无需投入大量工作就能写出的任何东西都要好。
标签: ios ssl afnetworking