那么我们就先来知道一下 HTTPS 以及加密的相关知识, 毕竟这也是面试比较常问到的点.
HTTP 与 HTTPS
HTTP 协议中,发送的内容是以明文的形式传递的。这就导致了以下几个 HTTP
的不足:
- 参数, 头信息等全为明文内容,很容易被窃听
- 不对双方的身份作验证,容易被伪装
- 无法验证数据的完整性,数据容易被篡改
也就是说很容易会被抓包, cookie等问题.但通过 SSL
(Secure Socket Layer
,安全套接层)或 TLS
(Transport Layer Security
,安全层传输协议)的组合使用,加密 HTTP
的通信内容。与 SSL
组合使用的 HTTP
被称为 HTTPS
(HTTP Secure
,超文本传输安全协议)或 HTTP over SSL
。
HTTPS的特点
HTTPS
在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。
TLS
/SSL
中使用了非对称加密,对称加密以及HASH
算法。其中非对称加密算法用于在握手过程中加密生成的密码,对称加密算法用于对真正传输的数据进行加密,而HASH
算法用于验证数据的完整性。
TLS
握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。
需要注意的是 HTTPS 并非是一种新的协议, 只是基于 HTTP 协议之上通信接口部分用 SSL
和 TLS
协议代替而已。
HTTPS的执行过程
对称加密和非对称加密
- 对称加密:
即加密的密钥和解密的密钥相同. 也就是所说的私钥加密, 信息的发送方和接收方使用同一个密钥去加密和解密数据。
- 非对称加密
非对称加密将密钥分为公钥和私钥,公钥可以公开,私钥需要保密,客户端公钥加密的数据,服务端可以通过私钥来解密.
个人建议理解方法: 非对称性加密理解为锁是公开的. 任何人通过公钥把数据锁到里面, 只有服务器 (拥有私钥的人可以打开锁.)
HTTPS采用的加密方式
HTTPS 采用混合加密, 值得一提的是 SSL 使用的是非对称性加密.
SSL加密并不保护数据中心本身,而是确保了SSL加密设备的数据中心安全,可以监控企业中来往于数据中心的最终用户流量。
🙋♂️问: 为什么 HTTPS 采用混合加密的模式呢?为什么不全用公开密钥加密?
答: 因为非对称性加密效率低, 占用资源高, 但因其利用的往往是数学难题, 因此安全性更好。所以 HTTPS 充分利用两者优势,在交换秘钥环节使用公开密钥加密方式,之后的简历通信交换报文阶段则用时共享秘钥加密方式.
上图步骤一就是非对称性加密秘钥, 步骤二数据交互时采用对称性加密方式.
简单来说就是通过非对称性加密 加密一个随机数, 这个随机数为对称性加密的钥匙.
举个例子: AES256 对称性加密, 他有一个 key, 这个 key 我们使用 RSA 去加密, 那么就构成了上述这种结构, 通过非对称性加密去加密对称性加密的钥匙.
Alamofire中的安全认证
直接找 ServerTrustPolicy
文件.
步骤 1️⃣: ServerTrustPolicyManager
初始化创建了一个
[String:ServerTrustPolicy]
属性.
步骤 2️⃣: 找到 ServerTrustPolicy
, 是一个枚举
public enum ServerTrustPolicy {
case performDefaultEvaluation(validateHost: Bool)
case performRevokedEvaluation(validateHost: Bool, revocationFlags: CFOptionFlags)
case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool)
case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
case disableEvaluation
case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool)
.performDefaultEvaluation
默认策略,只有合法证书才能通过验证.performRevokedEvaluation
对注销证书做的一种额外设置.pinCertificates
证书验证模式,代表客户端会将服务器返回的证书和本地保存的证书中的 所有内容 全部进行校验,如果正确,才继续执行。
pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
参数1:
certificates
证书
参数2:validateCertificateChain
代表是否验证证书链, 传false
则只验证根证书.
参数3:validateHost
代表是否验证子地址
使用 🌰:
let serverTrustPlolicies:[String: ServerTrustPolicy] = [
hostUrl: .pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true)
]
let sessionManger = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPlolicies))
sessionManger.request(urlString).response { (defaultResponse) in
print(defaultResponse)
}
-
.pinPublicKeys
公钥验证模式,代表客户端会将服务器返回的证书和本地保存的证书中的 PublicKey部分 进行校验,如果正确,才继续执行。
pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
参数1: 第一个参数传公钥
参数2:validateCertificateChain
代表是否验证证书链, 传false
则只验证根证书.
参数3:validateHost
代表是否验证子地址
公钥验证模式的好处是,只要公钥不变,就可以一直使用,不用担心证书问题。
.disableEvaluation
该选项下验证一直都是通过的,无条件信任。.customEvaluation
自定义验证,需要返回一个布尔类型的结果。
主要方法:
public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool
该方法是在 SessionDelegate
的 didReceive challenge
方法中调用的.
该类中还提供了一些辅助方法:
- 读取证书
public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate]
private func certificateData(for certificates: [SecCertificate]) -> [Data]
private func certificateData(for trust: SecTrust) -> [Data]
- 读取公钥
public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey]
private static func publicKeys(for trust: SecTrust) -> [SecKey]
private static func publicKey(for certificate: SecCertificate) -> SecKey?
- 获取验证结果
private func trustIsValid(_ trust: SecTrust) -> Bool
以上就是 HTTPS 的流程以及 Alamofire 中安全验证流程. 总结完毕