前言
随着 iOS9 的发布以及对 iOS 平台的安全问题的关注度的提高,iOS 安全问题慢慢被提上日程。最近了解了一下 iOS9 下 Https 的相关实现,和大家分享一下。
Https 浅析
Https 和 http 有何异同
https 和 http 从数据解析和交换来说本质上没有任何区别,https 可以看做经过校验和加密的 http 通信。也可以说在网络应用层,http+ssl/tsl 形成了 https。
Https 的通信过程
- 客户端产生一个随机数,将这个随机数以及客户端支持的加密算法发送给服务器.
- 服务器接到请求,确认双方使用的加密算法并产生第二个随机数,把证书和第二个随机数发送给客户端
- 客户端接收到证书之后验证服务器的身份。无效,则取消连接。有效,则生成第三个随机数,领用证书中的公钥对第三个随机数进行加密,传输给服务器。
- 服务器接收到第三个随机数后利用服务器上的私钥进行解密,然后得到第三个随机数
- 客户端和服务器使用这个三个随机数生成的“对话秘钥”进行加密,进行后续的通信过程。
安全性的保证:
虽然第一个和第二个随机数是明文,但是第三个随机数使用非对称加密方法进行加密,而且私钥从来没有在网络中进行传输,从理论上讲整个通信过程是安全的。
相关概念解释
SSL/TLS 看这里:
SSL/TLS 协议运行机制的概述
图解 SSL/TLS 协议
SSL/TLS 版本相关
数字证书:
该证书包含了公钥等信息,一般是由服务器发给客户端,接收方通过验证这个证书是不是由信赖的 CA 签发,或者与本地的证书相对比,来判断证书是否可信;假如需要双向验证,则服务器和客户端都需要发送数字证书给对方验证;
数字证书是一个电子文档,其中包含了持有者的信息、公钥以及证明该证书有效的数字签名。而数字证书以及相关的公钥管理和验证等技术组成了 PKI(公钥基础设施)规范体系。一般来说,数字证书是由数字证书认证机构(Certificate authority,即 CA)来负责签发和管理,并承担 PKI 体系中公钥合法性的检验责任;数字证书的类型有很多,而 HTTPS 使用的是 SSL 证书。
怎么来验证数字证书是由 CA 签发的,而不是第三方伪造的呢? 在回答这个问题前,我们需要先了解 CA 的组织结构。首先,CA 组织结构中,最顶层的就是根 CA,根 CA 下可以授权给多个二级 CA,而二级 CA 又可以授权多个三级 CA,所以 CA 的组织结构是一个树结构。对于 SSL 证书市场来说,主要被 Symantec(旗下有 VeriSign 和 GeoTrust)、Comodo SSL、Go Daddy 和 GlobalSign 瓜分。 了解了 CA 的组织结构后,来看看数字证书的签发流程。
数字证书的签发机构 CA,在接收到申请者的资料后进行核对并确定信息的真实有效,然后就会制作一份符合 X.509 标准的文件。证书中的证书内容包括了持有者信息和公钥等都是由申请者提供的,而数字签名则是 CA 机构对证书内容进行 hash 加密后等到的,而这个数字签名就是我们验证证书是否是有可信 CA 签发的数据。
接收端接到一份数字证书 Cer1 后,对证书的内容做 Hash 等到 H1;然后在签发该证书的机构 CA1 的数字证书中找到公钥,对证书上数字签名进行解密,得到证书 Cer1 签名的 Hash 摘要 H2;对比 H1 和 H2,假如相等,则表示证书没有被篡改。但这个时候还是不知道 CA 是否是合法的,我们看到上图中有 CA 机构的数字证书,这个证书是公开的,所有人都可以获取到。而这个证书中的数字签名是上一级生成的,所以可以这样一直递归验证下去,直到根 CA。根 CA 是自验证的,即他的数字签名是由自己的私钥来生成的。合法的根 CA 会被浏览器和操作系统加入到权威信任 CA 列表中,这样就完成了最终的验证。所以,一定要保护好自己环境(浏览器/操作系统)中根 CA 信任列表,信任了根 CA 就表示信任所有根 CA 下所有子级 CA 所签发的证书,不要随便添加根 CA 证书。
Https 实现(iOS)
证书准备
创建私钥:
openssl genrsa -out root/root-key.pem 1024
创建证书请求:
openssl req -new -out root/root-req.csr -key root/root-key.pem
自签署证书:
openssl x509 -req -in root/root-req.csr -out root/root-cert.pem -signkey root/root-key.pem -days 3650
将证书导出成浏览器支持的.p12 格式:
openssl pkcs12 -export -clcerts -in root/root-cert.pem -inkey root/root-key.pem -out root/root.p12
因为我们只需要验证一次证书,我们只需要创建一次就好了,不需要像原文那样创建那么多。我们客户端需呀的 cer 文件也可以由 pem 文件直接转换导出即可。
NSURLConnection 实现
1 | 系统默认验证流程 |
AFNetworking 对 Https 的支持
因为 AFNetworking 直接会遍历 bundle 找到对应的 cer 证书文件,故不需要添加证书路径,只需要把证书添加到工程中即可。
1 | NSURL _ url = [NSURL URLWithString:@"https://www.google.com"]; |
AFHTTPSessionManager 与之基本一致,不再详述。
参考博文: