一、HTTPS和HTTP的区别
HTTPS协议 = HTTP协议 + SSL/TLS协议
SSL的全称是Secure Sockets Layer,即安全套接层协议,是为网络通信提供安全及数据完整性的一种安全协议。TLS的全称是Transport Layer Security,即安全传输层协议。
即HTTPS是安全的HTTP。
二、HTTPS的连接建立流程
HTTPS为了兼顾安全与效率,同时使用了对称加密和非对称加密。在传输的过程中会涉及到三个密钥:
服务器端的公钥和私钥,用来进行
非对称加密
客户端生成的随机密钥,用来进行
对称加密
如上图,HTTPS连接过程大致可分为八步:
1、客户端访问HTTPS连接。
客户端会把安全协议版本号、客户端支持的加密算法列表、随机数C发给服务端。
2、服务端发送证书给客户端
服务端接收密钥算法配件后,会和自己支持的加密算法列表进行比对,如果不符合,则断开连接。否则,服务端会在该算法列表中,选择一种对称算法(如AES)、一种公钥算法(如具有特定秘钥长度的RSA)和一种MAC算法发给客户端。
服务器端有一个密钥对,即公钥和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥可以发送给任何人。
在发送加密算法的同时还会把数字证书和随机数S发送给客户端
3、客户端验证server证书
会对server公钥进行检查,验证其合法性,如果发现发现公钥有问题,那么HTTPS传输就无法继续。
4、客户端组装会话秘钥
如果公钥合格,那么客户端会用服务器公钥来生成一个前主秘钥(Pre-Master Secret,PMS),并通过该前主秘钥和随机数C、S来组装成会话秘钥
5、客户端将前主秘钥加密发送给服务端
是通过服务端的公钥来对前主秘钥进行非对称加密,发送给服务端
6、服务端通过私钥解密得到前主秘钥
服务端接收到加密信息后,用私钥解密得到前主秘钥。
7、服务端组装会话秘钥
服务端通过前主秘钥和随机数C、S来组装会话秘钥。
至此,服务端和客户端都已经知道了用于此次会话的主秘钥。
8、数据传输
客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据。
同理,服务端收到客户端发送来的密文,用服务端密钥对其进行对称解密,得到客户端发送的数据。
总结:
- 会话秘钥 = random S + random C + 前主秘钥
- HTTPS连接建立过程使用非对称加密,而非对称加密是很耗时的一种加密方式
- 后续通信过程使用对称加密,减少耗时所带来的性能损耗
其中,对称加密加密的是实际的数据,非对称加密加密的是对称加密所需要的客户端的密钥。
二、三次握手
数据开始传输前,需要通过 三次握手来建立连接
- 第一次握手:客户端尝试连接服务器,向服务器发送 syn 包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入 SYN_SEND 状态等待服务器确认
- 第二次握手:服务器接收客户端syn包并确认(ack=j+1),同时向客户端发送一个 SYN包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手这个阶段,同时可以在报文段负载中携带应用层数据。
收到客户端该报文段后,服务端TCP也会进入ESTABLISHED状态,可以发送和接收包含有效载荷数据的报文段。
下图是一张通俗的理解
三、四次挥手
参与TCP连接的两个进程中的任何一个都能终止该连接,当连接结束后,主机中的资源(缓存和变量)会被释放。
上边说到,SYN和FIN标志位分别对应着TCP连接的建立和拆除。
四、一些问题
1、问:为什么建立连接只用三次握手,而断开连接却要四次挥手?
- 首先,当客户端数据已发送完毕,且知道服务端也全部接收到了时,就会去断开连接即向服务端发送FIN
- 服务端接收到客户端的FIN,为了表示接收到了,就会向客户端发送ACK
- 但此时,服务端可能还在发送数据,并没有关闭TCP窗口的意思,所以服务端的FIN和ACK并不是同步发的,只有当数据发送完了,才会发送FIN
答:服务端的FIN和ACK需要分开发,并不是像三次握手中那样,SYN可以和ACK同步发,所以就需要四次挥手
2、Q:TCP在创建连接时,为什么需要三次握手而不是两次或四次?
- 之所以不用四次握手的原因很容易理解,就是浪费资源,服务端的SYN和ACK可以一起发,完全没必要分开两次。
- 而两次握手,仔细想一下,客户端在建立第一次连接后可能自己挂了,或者网络原因超时。重启后又重新开始第一次握手,但是如果服务端收到此失效的连接请求SYN报文段后,就确认。而不是再次和客户端确认,这不是就出错了么?
A:两次握手会可能导致已失效的连接请求报文段突然又传送到了服务端产生错误,四次握手又太浪费资源