如何为 AFNetworking 创建 .cer 文件以在 iOS 应用程序包中使用

Posted

技术标签:

【中文标题】如何为 AFNetworking 创建 .cer 文件以在 iOS 应用程序包中使用【英文标题】:How to create .cer file for AFNetworking to be used in iOS app bundle 【发布时间】:2015-03-19 22:29:51 【问题描述】:

我一直在网络上看到关于 .cer 文件是什么以及如何生成它以便应用程序可以通过 https 与服务器正确通信的脱节帐户。

引用this消息来源,有人说:

1) 您现在需要捆绑包中的 .cer 文件来获取链中的所有证书。因此,至少必须存在两个证书文件(您的证书和根 CA)。在我们的例子中,我们也需要一个中间体。

2) 这些证书必须按特定顺序排列。具体来说,证明您正在与之通信的主机的证书必须位于固定证书/密钥列表中的第一位。其余部分的顺序看起来并不重要。这是因为 AFSecurityPolicy 使用数组中的第一个对象来验证主机名。

3) 如果您与根域通信,则通配符证书的主机验证失败。例如,考虑指向 *.foo.com 的证书。如果您与 foo.com 通信,主机检查将失败,因为主机组件计数不匹配。我理解这种早期优化的必要性,但它甚至在达到专门处理通配符域的逻辑之前就失败了。

官方文档支持here。

我想为了生成它,必须将整个证书链的内容按特定顺序放入 .cer 文件中。我记得在某个地方看到过这个帖子,但似乎找不到。

问题是,为 AFNetworking 创建 .cer 文件的无可争议的方法是什么?

更新:

经过更多研究,在我看来,您只需获取 .crt 文件并对其执行以下操作:

openssl x509 -in www.mydomain.com.crt -out www.mydomain.com.cer -outform der

但是,即使在执行此操作并将 .cer 附加到我的应用程序包之后,我也会在此处收到错误:

+ (NSArray *)pinnedPublicKeys 
    static NSArray *_pinnedPublicKeys = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
        NSArray *pinnedCertificates = [self pinnedCertificates];
        NSMutableArray *publicKeys = [NSMutableArray arrayWithCapacity:[pinnedCertificates count]];

    for (NSData *data in pinnedCertificates) 
        SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
        NSParameterAssert(allowedCertificate);

错误出现在最后一行。我想在它尝试分配allowedCertificate 的前一行中,SecCertificateCreateWithData 具有以下描述:

/*!
    @function SecCertificateCreateWithData
    @abstract Create a certificate given it's DER representation as a CFData.
    @param allocator CFAllocator to allocate the certificate with.
    @param certificate DER encoded X.509 certificate.
    @result Return NULL if the passed-in data is not a valid DER-encoded
    X.509 certificate, return a SecCertificateRef otherwise.
*/

显然它返回一个 NULL,但我不知道为什么。我的特定证书格式正确。但是,我确实注意到pinnedCertificates 数组中还有其他“证书”,但我不知道它从哪里得到它们。我似乎也找不到它们或打印出来。据我所知,我在 app bundle 中只有一个,但它似乎显示的不止这些。

最后一行assert产生的错误是:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: allowedCertificate'

【问题讨论】:

【参考方案1】:

假设您使用的是 AFNetworking 2.5,步骤如下所述:

在您的服务器上安装有效证书

创建 .cer 文件openssl x509 -in www_yourdomain_com.crt -out www_yourdomain_com.cer -outform der

将 .cer 文件添加到应用项目。重要提示:切勿将私钥添加到您的项目中!!!

设置 AFNetworking 安全策略

- (AFSecurityPolicy *)securityPolicy 
   AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
   [securityPolicy setAllowInvalidCertificates:NO];
   [securityPolicy setValidatesDomainName:YES];
   return securityPolicy;

在进行网络调用时设置网络管理器的策略

 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
 [manager setSecurityPolicy:[self securityPolicy]];

如果您使用policyWithPinningMode:pinningMode 方法创建安全策略,则无需手动加载 .cer 文件,AFNetworking 会自动固定它们。

【讨论】:

感谢您的回复。我不认为这很简单,因为它仍然不起作用。中级证书呢?是否也需要将其连接到 .cer 文件中?我要试试。 ssldecoder.org 对我的证书链很满意,但是当我只是将站点 .crt 转换为 .cer 时,我的应用程序就会崩溃。 它没有用。 AFNetworking 似乎不喜欢证书文件。 使用上述设置时,您是否会收到特定错误或静默失败? 在遍历pinned证书时(有3个),碰到这两行的NSAssert时抛出异常SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); NSParameterAssert(allowedCertificate); 通过将多个证书添加到安全策略的 pinnedCertificates 数组来固定多个证书: let policy: AFSecurityPolicy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.Certificate) let path: String? = NSBundle.mainBundle().pathForResource("mycert", ofType: "cer") 让 keyData: NSData = NSData(contentsOfFile: path!)! policy.pinnedCertificates = [keyData] 如果您有多个证书,请将它们全部添加:[keyData1, keyData2 etc]

以上是关于如何为 AFNetworking 创建 .cer 文件以在 iOS 应用程序包中使用的主要内容,如果未能解决你的问题,请参考以下文章

如何为已弃用的 AFNetworking 2.0 传递授权令牌

AFNetworking - SSL - 添加了 .cer 文件,但在服务器端出现 400 错误

CFNetwork SSLHandshake 因 AFNetworking 2.0、自签名 cer 和 [policy setAllowInvalidCertificates:YES] 而失败

如何为不同的请求方法创建具有不同参数编码的 AFHttpClient?

AFNetworking 2 无法使用自签名证书

使用 AFNetworking 进行 SSL 固定 - validatesCertificateChain = true