【网络】Https流程解析

本文介绍了Https通信协议的相关内容
HTTP over SSL 的简称,即⼯作在 SSL (或 TLS)上的 HTTP。说⽩了就是加密通信的 HTTP,注意并不是一个单独的协议。HTTPS(SSL/TLS)是计算机网络的知识,主要用来对HTTP协议传输的文本进行加密,提高安全性的一种协议。
- SSL:Secure Socket Layer
- TSL: Transport Layer Secure
因为HTTP是明文传输,所以会很有可能产生中间人攻击(获取并篡改传输在客户端及服务端的信息并不被人发觉),HTTPS加密应运而生。在HTTP之下增加一个安全层,其位于HTTP和TCP之间,更靠近应用层,作用是来加密解密。
本质:在客户端和服务器之间协商出⼀套对称密钥,每次发送信息之前将内容加密,收到之后解密,达到内容的加密传输。 用非对称加密来商讨出一套对称式密钥,再用这个对称密钥来通信。
为啥不直接用非对称加密通信?因为非对称加密效率低,速度慢。
实现流程:
- 客户端请求建立TLS连接
- 服务器发回证书
- 客户端验证服务器的证书
- 客户端新任服务器之后,和服务器协商对称密钥
- 最后使用对称密钥开始通信
最后一步才进入HTTP通信的范畴,前面均是TCP通信。
- Client Hello 客户端跟服务器请求建立连接,附带告诉服务器,我所支持的TLS版本,还有Cipher Suite加密套件,里面是客户端支持的对称加密算法,非对称加密算法,Hash算法。同时还有一个随机数X。
- Server Hello 服务器给客户端返回数据,选择好TLS版本,算法等。同时返回一个随机数Y。
- 服务器给客户端发送证书,里面核心是非对称加密的公钥,还有服务器的域名,地址,等信息,最后还有服务器的签名,对本次传输所有数据进行签名,表明确实是这个服务器所发。还有证书机构的公钥和证书机构的其他信息签名来对这个服务器的证明数据进行签名,即下图黄色机构对蓝色数据进行签名证明。但是只是可以说明数据确实是由这个公钥对应私钥的持有者所签发。还需要根证书机构的签名对证书机构的签名进行签名,即紫色根证书机构对黄色的证书机构进行签名证明。这个根证书机构的验证来自操作系统内部,到了这一层如果签名能对得上,就可以确定来源的可信了。

根证书的来源:在操作系统生产出的时候,被研发方所认证了的,级上方为一个信任链,到最底层的根证书列表就需要无条件信任。根证书机构很忙,需要一个中间机构去分担压力。
- 服务器证书验证就通过了。客户端浏览器拿到服务器公钥的时候,使用这个公钥加密一个信息: Pre-master Secret,这也是一个随机数。整个通信过程中唯一一次非对称加密来处理的数据。现在就有三个随机数了,X, Y, Pre-master Secret。前两个随机数X, Y大家都能看见,虽然是明文传输,但加上之后就可以使密钥更安全。现在双方就有足够的信息来生产一个对称加密的密钥了。即Master Secret。这个密钥实际上包含四个东西:客户端加密密钥,服务端加密密钥,客户端Hash Key,服务端Hash Key。HMAC:hash-based message authenticate code,改良版的Hash算法。虽然是对称加密,服务端和客户端之间的通信仍然是用不同的加密密钥来通信,客户端发送时使用客户端加密密钥来加密,服务端接收到之后,使用客户端密钥来解密。用作证明身份,双方都会用MAC Secret来作签名和验证。
- 双方作一次验证,看上面沟通的加密算法能不能用。
简要的连接建立过程:
- Client Hello
- Server Hello
- 服务器证书 信任建⽴
- Pre-master Secret
- 客户端通知:将使⽤加密通信
- 客户端发送:Finished
- 服务器通知:将使⽤加密通信
- 服务器发送:Finished
问题:如果另一个拥有合法证书的机构把消息拦截下来,而且也发生给客户端一份完整的ServerHello返给客户端,这样可以建立起HTTPS连接吗? 客户端请求时,会将要访问的Host地址附加在报文里。同样,在服务端的证书包里,也会附加Host名。客户端收到之后,会对Host主机地址进行校验,只有两者域名一致才能通过验证继续往下建立连接。签发证书的机构会将证书和域名进行绑定。
安全性
非对称加密可以防范中间人攻击吗?
鉴于非对称加密的机制,我们可能会有这种思路:服务器先把公钥以明文方式传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,这条数据的安全似乎可以保障了!因为只有服务器有相应的私钥能解开公钥加密的数据。
然而反过来由服务器到浏览器的这条路怎么保障安全?如果服务器用它的私钥加密数据传给浏览器,那么浏览器用公钥可以解密它,而这个公钥是一开始通过明文传输给浏览器的,若这个公钥被中间人劫持到了,那他也能用该公钥解密服务器传来的信息了。所以目前似乎只能保证由浏览器向服务器传输数据的安全性。用两组私钥公钥对即可解决。
所以我们证明了一组公钥私钥,至少可以确保单向的数据安全,那么我可不可以合理推断如果我有两组公钥私钥,那我就可以保证双向数据传输的安全了呢?
某网站服务器拥有公钥A与对应的私钥A’;浏览器拥有公钥B与对应的私钥B’。
浏览器把公钥B明文传输给服务器。
服务器把公钥A明文给传输浏览器。
之后浏览器向服务器传输的内容都用公钥A加密,服务器收到后用私钥A’解密。由于只有服务器拥有私钥A’,所以能保证这条数据的安全。
同理,服务器向浏览器传输的内容都用公钥B加密,浏览器收到后用私钥B’解密。 同上也可以保证这条数据的安全。
bingo!好像成功了!但是这个方法并没有被大范围推广,并且也不可能被大范围推广。很重要的原因是非对称加密算法非常耗时,而对称加密快很多。
好家伙,说来说去又回到对称加密了,合着你就非得用对称加密是吗?
对!就是要找一个方法,让客户端和服务端都知道那个公共密钥并且确保第三方不会获取,那我就是可以放心的使用对称加密传输数据了
对称加密和非对称加密的综合版本
某网站拥有用于非对称加密的公钥A、私钥A’
浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。
浏览器随机生成一个用于对称加密的密钥X,用公钥A加密后传给服务器。
服务器拿到后用私钥A’解密得到密钥X。
这样双方就都拥有密钥X了,且别人无法知道它。之后双方所有数据都通过密钥X加密解密即可。
成功!HTTPS基本就是采用了这种方案。
但是这并不是完美的,这仍然有漏洞喔!
对称加密和非对称加密的综合版本的漏洞
如果在数据传输过程中,中间人劫持到了数据,此时他的确无法得到浏览器生成的密钥X,这个密钥本身被公钥A加密了,只有服务器才有私钥A’解开它,然而中间人却完全不需要拿到私钥A’就能干坏事了。请看:
- 某网站有用于非对称加密的公钥A、私钥A’。
- 浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。
- 中间人劫持到公钥A,保存下来,把数据包中的公钥A替换成自己伪造的公钥B(它当然也拥有公钥B对应的私钥B’)。
- 浏览器生成一个用于对称加密的密钥X,用公钥B(浏览器以为是公钥A)加密后传给服务器。
- 中间人劫持后用私钥B’解密得到密钥X,再用公钥A加密后传给服务器(保证两方通信能顺利进行)。
- 服务器拿到后用私钥A’解密得到密钥X。
这样在双方都不会发现异常的情况下,中间人通过一套“狸猫换太子”的操作,掉包了服务器传来的公钥,进而得到了密钥X。根本原因是客户端浏览器无法确认收到的公钥是不是服务器发来的,因为公钥本身是明文传输的。
所以!我们只剩下最后一个问题,那就是怎么确保浏览器收到的公钥是网站的,而不是中间人的!
网站在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书持有者信息、公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明“该公钥对应该网站”。而这里又有一个显而易见的问题,“证书本身的传输过程中,如何防止被篡改”?
注意这个CA机构需要完全可信,他的证明需要是有效的。
服务器将自己的公钥,Hash后用服务器的私钥制作签名。再将CA机构的证书一同打包发送给客户端。


每次发送HTTPS请求都需要在TLS/SSL层进行握手传输密钥吗?
如果是的话,那也太浪费资源和时间了吧。
服务器会为每个浏览器(或客户端软件)维护一个session ID,在TLS握手阶段传给浏览器,浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的session ID下,之后浏览器每次请求都会携带session ID,服务器会根据session ID找到相应的密钥并进行解密加密操作,这样就不必要每次重新制作、传输密钥了!
在Android中使用时
一般都是正常用即可。
需要自己写证书验证过程的场景:
- ⽤的是⾃签名证书(例如只⽤于内⽹的 https)
- 证书信息不全,缺乏中间证书机构(可能性不⼤)
- ⼿机操作系统较旧,没有安装最新加⼊的根证书