HTTP 运行在了安全的 SSL/TLS 协议上。把 HTTP 下层的传输协议由 TCP/IP 换成了 SSL/TLS。
HTTPS的引入为了解决HTTP协议传输机密性、完整性、身份认证、不可否认等相关的安全问题。
一、HTTPS密码套件
浏览器和服务器在使用 TLS 建立连接时需要选择一组恰当的加密算法来实现安全通信,这些算法的组合被称为“密码套件”(cipher suite,也叫加密套件)。
其基本形式为:密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法。
例如ECDHE-RSA-AES256-GCM-SHA384。
握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM,摘要算法 SHA384 用于消息认证和产生随机数。
HTTPS利用非对称加密交换秘钥,用对称加密算法传输。以此来保证机密性。
利用摘要算法保证信息的完成性。
利用数字证书解决身份认证问题,数字证书因为CA机构的信任变成一个完整信任链条,从而实现通过数字证书证明了对方真实身份。
数字签名解决不可否认问题,数字签名也是通过非对称加密实现。由于效率问题数字签名只加密原文的摘要。
HTTPS连接过程
二、HTTPS 建立连接
HTTPS在TCP之上建立连接,这个握手过程与TCP类似,
TLS协议
TLS 包含几个子协议,你也可以理解为它是由几个不同职责的模块组成,比较常用的有记录协议、警报协议、握手协议、变更密码规范协议等。
记录协议(Record Protocol) 规定了 TLS 收发数据的基本单位:记录(record)。它有点像是 TCP 里的 segment,所有的其他子协议都需要通过记录协议发出。但多个记录数据可以在一个 TCP 包里一次性发出,也并不需要像 TCP 那样返回 ACK。
警报协议(Alert Protocol) 的职责是向对方发出警报信息,有点像是 HTTP 协议里的状态码。比如,protocol_version 就是不支持旧版本,bad_certificate 就是证书有问题,收到警报后另一方可以选择继续,也可以立即终止连接。
握手协议(Handshake Protocol) 是TLS 里最复杂的子协议,要比 TCP 的 SYN/ACK 复杂的多,浏览器和服务器会在握手过程中协商 TLS 版本号、随机数、密码套件等信息,然后交换证书和密钥参数,最终双方协商得到会话密钥,用于后续的混合加密系统。
变更密码规范协议(Change Cipher Spec Protocol) 它非常简单,就是一个“通知”,告诉对方,后续的数据都将使用加密保护。那么反过来,在它之前,数据都是明文的。
TLS1.2握手过程
TLS握手过程如下图所示:
- 在TCP建立连接之后,客户端会首先发一个“Client Hello”消息。里面有客户端的版本号、支持的密码套件,还有一个随机数(Client Random),用于后续生成会话密钥。
- 服务器收到“Client Hello”后,会返回一个“Server Hello”消息。把版本号对一下,也给出一个随机数(Server Random),然后从客户端的列表里选一个作为本次通信使用的密码套件。
- 服务器为了证明自己的身份,就把证书也发给了客户端(Server Certificate)。
- 因为服务器选择了算法,所以它会在证书后发送“Server Key Exchange”消息,里面是椭圆曲线的公钥(Server Params),用来实现密钥交换算法,再加上自己的私钥签名认证。
- 之后是“Server Hello Done”消息。
这样第一个消息往返就结束了(两个TCP包),结果是客户端和服务器通过明文共享了三个信息:Client Random、Server Random 和 Server Params。
- 客户端按照密码套件的要求,也生成一个椭圆曲线的公钥(Client Params),用“Client Key Exchange”消息发给服务器。
- 现在客户端和服务器手里都拿到了密钥交换算法的两个参数(Client Params、Server Params),就用算出了一个新的东西,叫“Pre-Master”,其实也是一个随机数。
- 现在客户端和服务器手里有了三个随机数:Client Random、Server Random和Pre-Master。用这三个作为原始材料,就可以生成用于加密会话的主密钥,叫“Master Secret”。而黑客因为拿不到“Pre-Master”,所以也就得不到主密钥。
- 有了主密钥和派生的会话密钥,握手就快结束了。客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。
- 服务器也是同样的操作,发“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应了。
- 接下来就是HTTP的通信过程
以上是TLS1.2的握手过程,现在因为密码套件大幅度简化,也就没有必要再像以前那样走复杂的协商流程了。TLS1.3 压缩了以前的“Hello”协商过程,删除了“Key Exchange”消息,把握手效率提高了一倍。
TLS1.3握手过程
TLS握手过程如下图所示:
- 表面上看和 TLS1.2 是一样的,重点是后面的扩展。“supported_versions”里确认使用的是 TLS1.3,然后在“key_share”扩展带上曲线和对应的公钥参数。
- 这时只交换了两条消息,客户端和服务器就拿到了四个共享信息:Client Random 和 Server Random、Client Params 和 Server Params,两边就可以各自用 ECDHE 算出“Pre-Master”,再用 HKDF 生成主密钥“Master Secret”,效率比 TLS1.2 提高了一大截。
- 在算出主密钥后,服务器立刻发出“Change Cipher Spec”消息,比 TLS1.2 提早进入加密通信,后面的证书等就都是加密的了,减少了握手时的明文信息泄露。
- 这里 TLS1.3 还有一个安全强化措施,多了个“Certificate Verify”消息,用服务器的私钥把前面的曲线、套件、参数等握手数据加了签名,作用和“Finished”消息差不多。但由于是私钥签名,所以强化了身份认证和和防窜改。
- 接下来就是HTTP的通信过程