HTTP 协议是使用明文进行数据传输的,这感觉就像是在互联网上裸奔一样,只要能够截获请求,就可以窃听你传输的信息,并还可以进行篡改数据,甚至冒充用户进行通信
所以,为了保证数据传输的安全性,就需要对传输的数据进行加密,这样的话即便数据被其他人截获了,也拿不到真正请求的数据信息
HTTPS 就是在 HTTP 的基础之上,添加了数据加密传输的功能,而 HTTPS 使用的协议就是 TLS/SSL
TLS 和 SSL
TLS是传输层安全的缩写,SSL 是安全套接字层的安全,都是加密数据和 internet
上确保数据安全传输的协议
-
那它们有什么区别呢
SSL 是 Netscape 公司提出的安全保密协议,在浏览器和服务器之间构造安全通道来进行数据传输,它是运行在
TCP/IP
层之上,在应用层之下的协议1994年,
Netscaoe
公司设计了SSL
协议(Secure Sockets Layer
),之后又对该版本进行了升级;1996年,
SSL3.0
版本问世,并且得到了广泛的应用TLS
是后面互联网标准化组织ISOC
接替了Netscape
公司,在 1999 年分布了SSL
的升级版本TLS1.0
版本之后,在2006年和2008年,
TLS
进行了两次升级,分别为TLS 1.1版和TLS 1.2版。最新的变动是2011年TLS 1.2的修订版。目前,应用最广泛的是TLS 1.0,接下来是SSL 3.0。但是,主流浏览器都已经实现了TLS 1.2的支持。
TLS 1.0通常被标识为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。
-
基本运行过程
TLS/SSL 协议的基本思想就是使用公钥加密法,首先客户端向服务器索要公钥,获取到公钥之后,然后加密数据进行传输;服务端收到客户端传来的加密数据之后,使用私钥对数据进行解密
那如何保证公钥不被篡改呢?
解决办法:将公钥放到数字证书当中,只要数字证书是安全的,那么公钥就是安全的
使用公钥加密的计算量很大,如何这个过程中耗用的时间呢
解决办法:客户端和服务器的每一次对话,都会产生一个"session key",也就是对话密钥,使用该密钥对数据进行对称加密,而公钥只用于加密对话密钥,因为对称加密的计算速度很快,所以整个加密过程的耗时就会减少
使用 TSL/SSL 通信的整个过程如下所示:
- 客户端向服务器索要公钥
- 双方协商"对话密钥"
- 双方采用”对话密钥”对数据进行加密
其中 1,2 步骤又称之为"握手阶段"
握手阶段的详细过程
"握手阶段"涉及四次通信,需要注意的是,"握手阶段"的所有通信都是明文的。
-
客户端发出加密通信的请求,向服务器提供如下的信息
(1) 支持的协议版本,比如TLS 1.0版。 (2) 一个客户端生成的随机数,稍后用于生成"对话密钥"。 (3) 支持的加密方法,比如RSA公钥加密。 (4) 支持的压缩方法。
-
- 服务接收到客户端的请求之后,向客户端响应
(1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。 (2) 一个服务器生成的随机数,稍后用于生成"对话密钥"。 (3) 确认使用的加密方法,比如RSA公钥加密。 (4) 服务器证书。
当然,一些金融机构还会要求服务器确认客户端的身份,要求客户端提供"客户端证书",因为金融机构往往只允许认证客户连入自己的网络,所以就会向客户提供
USB
密钥,在这个USB
密钥就包含了"客户端证书";这就是常用的U盾
客户端收到证书之后,首先就会验证服务器的证书是不是由可信的机构颁发的,以及证书是否已经过期,或证书中的域名是否与实际的域名是一样的,如果证书有问题,就会向客户端发出警告,由客户端选择是否还需要继续通信
如果证书没有问题,客户端就从证书中取出公钥,然后向服务器发送以下信息:
(1) 一个随机数。该随机数用服务器公钥加密,防止被窃听。
(2) 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
(3) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。
上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。
那为什么需要用三个随机数来生成通信的密钥呢?
"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"
当然,如果服务器还需要客户端的证书,客户端还会在这一步发送证书相关的信息
4 服务器收到客户端的响应之后,计算生成本次会话所用的"会话密钥"。然后,向客户端发送如下的信息:
(1)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。
至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。
- session 恢复
在握手阶段,如果处于某种原因,对话中断了,那么就需要重新握手,这不仅耗时而且浪费带宽;所以,有没有方法能够重新之前的会话呢?
现在有两种方法来恢复之前的会话,第一种就是使用 sessionID
,第二种就是使用sessionKey
SessionID
sessionID 就是说每次对话都有一个编号(sessionID
)。如果连接中断了,那么在下次重连时,只需要客户端向服务端提供了这个sessionID
,并且服务端有这个编号的记录,这样双方就可以重新使用之前的对话密钥
,而不需要重新生成一把了
SessionKey
服务器生成一个sessionTiket
,这个sessionTicket
是加密的,里面包含本次对话的信息,包括对话密钥
和加密方法
等,这个sessionTicket
只有服务器能够解密。
在握手阶段,服务器将这个sessionTicket
发送给客户端,当出现断链的时候,客户端将这个sessionTicket
发送给服务端,服务器收到这个sessionTicket
以后,如果能够成功解密,那么就不需要再重新握手了
使用sessionTicket
就能够很好的解决sessionID
中由于集群问题带来的不同服务器中数据不一致的问题了
参考链接:
https://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
https://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html