代码改变世界

HTTPS到底是个什么鬼?

2017-03-12 20:58  hduhans  阅读(917)  评论(0编辑  收藏  举报

  HTTPS随处可见,那么它到底是个什么鬼?本文我们一起来探讨一下HTTPS为什么是安全的,以及HTTPS连接建立的过程。

一、HTTPS为什么是安全的?

  HTTP使用明文通信,可能会被第三方窃听、篡改和冒充,所以它是不安全的。那么HTTPS为什么是安全的呢,它到底是怎样保证安全的呢?

1、简单通信加密

  如果A需要向B发送数据,怎么保证数据在通信过程中的隐私性呢?答案是使用加密算法,从《了解数字证书、数字签名与常见的加密算法》了解到可以使用对称加密算法来对通信的数据进行加密,这样就可以保证通信过程中数据的隐私性和安全性。做法是,如果通信双方A和B事先已知,则他们可以事先线下商定好一个对称加密算法和密钥,然后进行数据通信,如图1.1。但是,在互联网环境中,往往通信一方是未知的,并且所有数据必须走网络,此时如果直接使用明文传输密钥还是会被截获,通信仍然是不安全的。那么此时如何将密钥发给对方呢?

图1.1 使用相同的对称加密密钥进行数据通信

2、使用非对称加密来传输对称密钥

  聪明的设计者想到了,可以使用非对称加密来解决密钥交换的问题。在非对称加密中,使用A的公钥加密数据发送给A是安全的,因此问题到这里就变成了B如何安全地获得A的公钥。思考一下,A直接将他的公钥发给B有没有安全风险呢?答案是有的,直接发送公钥存在被中间人调包的风险,假设M为中间人,通信调包过程见图1.2(右键放大查看)。

图1.2 中间人通过调包公钥实现通信监听与篡改

  从图中可知,直接发送A的公钥是存在被中间人调包的风险的,那么在下发A的公钥的时候如何保证公钥不被调包呢?

3、使用三方机构来确保服务器公钥下发的安全性

  到这里,单单依赖A和B本身是很难实现A公钥下发的安全性的,此时需要依靠三方CA机构来保证A公钥下发的安全性。此时需要A找一家权威的CA机构,将自己的公钥发给他来申请数字证书,然后CA会使用自己的私钥对A的公钥和A的其他信息进行加密,制作证书。通常情况下,A的身份是web服务器,B身份是浏览器,此时证书做好后A就将数字证书部署到自己服务器中。当浏览器B来请求公钥时,服务器A就将带有A公钥的数字证书发送过去,浏览器B接收到数字证书后,会根据证书中的CA机构信息在本地环境中找到预存的CA公钥(权威CA机构的公钥通常预先内置于操作系统或浏览器中)校验证书的安全性,然后获得服务器A的公钥了(数字证书相关参考《了解数字证书、数字签名与常见的加密算法》)。

  事实上,浏览器B收到服务器A的证书后,先使用本地预存的对应CA的公钥对证书内的数字签名进行验证。验证数字证书后,浏览器B会生成一个随机的字符串,用服务器A的公钥进行加密并发送给服务器A,服务器A用私钥先解密再加密后把结果返回给浏览器B,浏览器B用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是服务器A。

  细心的你可能会发现,虽然数字证书无法伪造,但是此时还是有调包数字证书的可能性,就是中间人也向CA机构申请证书(可以相同也可以不同),将自己的证书替换网站A的证书下发给浏览器B,后续监听与篡改与图2类似。那么说,数字证书岂不是还是没起到作用?

  其实,浏览器在收到数字证书后,会进行一系列的安全校验,其中最重要的就是需要校验当前访问的网址是否与证书中的网址匹配,如果不匹配,则存在证书被替换风险,会发出风险警告。几乎所有的浏览器都支持CA证书与校验,演变到这一步,已经完全可以实现网站A公钥下发的安全性保障了。

  -----------------

  浏览器如何验证数字证书?

  1) 验证证书的真伪

  浏览器拿到证书后会根据颁发机构去本地系统CA证书库找到对应证书,取出发证机关的公钥,并用此公钥解密数字签名值获取网站公钥的摘要值即为DIG1,再用相同的摘要算法对网站公钥进行计算获取值为DIG2,若DIG1=DIG2,则表示此证书为的确为该颁发机构颁发的真实证书,未被篡改。

  2) 验证当前证书持有者的真伪

  第一步验证证书真伪后,需要再验证当前持有者是否为所有者(注意持有者和所有者的区别)。验证方法是,用网站的公钥加密一段随机信息给当前持有者(当前访问网站),如果持有者能顺利解密并返回(可以返回明文,或返回摘要计算后的值,或使用网站的私钥进行加密后的密文),浏览器再根据对应的方法验证返回的数值是否为原信息,一致则表示当前证书持有者(同新方)就是证书所有者。

  3) 验证证书所有者的姓名

  这一步就是验证证书的域名与当前访问域名是否一致。

  -----------------

  数字证书中的公钥是以密文形式存在,并且数字证书中还包含对该公钥的数字签名。如果有中间人试图篡改公钥信息,客户端在接收证书后是通不过数字签名的校验的,因此使用数字证书下发的公钥,是安全的。

  所以综合以上三点:对称加密算法加密数据 + 非对称加密算法交换密钥 + 数字证书验证身份 = 安全

二、HTTPS是怎样建立连接的?

  客户端与服务端需要经过握手阶段才能建立HTTPS连接,握手过程如图2.1所示。我们将通过wireshark抓包支付宝主页(https://www.alipay.com/)来逐步了解具体通信过程。

图2.1 https握手连接示意图

     

1、客户端发起Client Hello

  tcp三次握手后,客户端开始发起Client Hello请求,如图2.2所示。  

图2.2 Client Hello请求抓包数据 

  1) 随机数。这是整个连接过程中的第一个随机数,我们先记为ClientHello.random,后续生成对称密钥会用到;

  2) Session Id。用于下次建立https连接时,可直接使用,避免重复握手,以提高效率(类似于web的session)。这里由于是第一次访问alipay,所以SID为空;

  3) Cipher Suites-密文族。是浏览器所支持加密算法的清单,供服务器选择。以"TLS_RSA_WITH_AES_256_CBC_SHA"为例,TLS为协议,RSA为密钥交换的算法,AES_256_CBC是对称加密算法(其中256是密钥长度,CBC是分组方式),SHA是哈希的算法。

  4) server_name扩展。一个ip可能配置有多个https域名,此时需要向服务器指定需要请求哪个域名的证书;

  5) Compression Methods。客户端支持的压缩算法,供服务器选择。

2、服务端回复Server Hello

  图2.3 Server Hello抓包数据

  1) Session ID。服务端新生成供客户端下次请求时复用(如果客户端请求带有SID并且服务端已存在则直接复用,不新创建);

  2) Cipher Suite。服务端选择的加密算法。

  大多数HTTPS握手在Server Hello返回时会带上客户端所需要的证书,而此实验发现此时并没有返回证书。往下看,发现在Server Hello Done时返回了证书。

3、服务端响应Sever Hello Done

图2.4 Server Hello Done抓包数据

  这里在Server Hello Done响应时,同时给客户端返回了证书,告诉客户端hello结束。

4、客户端验证证书

  这一步非常关键,客户端需要校验服务端下发的证书的真实性。主要靠证书中自带的数字签名算法进行校验,同时会比较当前访问站点与证书中的域名是否一致,如不一致则需要发出预警。

5、客户端密钥交换Client Key Exchange

图2.5 客户端密钥交换抓包数据

  此步骤密钥交换算法比较复杂,客户端生成第三个随机数PreMaster并加密传输给服务器,并不会直接加密传输生成后的对称密钥,会让服务器利用已知的三个随机数和相同的加密算法生成后续数据通信的对称密钥(不直接传输加密后的对称密钥可能出于更安全的角度考虑)。

6、服务端响应握手结束

图2.6 握手结束抓包数据

  至此,HTTPS握手已经结束,后续客户端与服务端通信都使用协商好的对称密钥进行加密通信。

其他

免费的https证书,参考:https://segmentfault.com/a/1190000012343679

参考资料

  《HTTPS 科普扫盲帖》 

  《SSL/TLS协议运行机制的概述

  《https连接的前几毫秒发生了什么

  《一个故事教你看懂什么是数字证书,它的原理是什么?它的作用是什么?