HTTPS原理深入解析

342 阅读14分钟

本文将从以下四个方面来讲解HTTPS:

  • HTTPS与HTTP有什么联系
  • HTTPS为什么比HTTP更安全
  • HTTPS的连接过程
  • HTTPS怎么防御中间人攻击

HTTPS与HTTP的关系

要说这个,首先得知道基本的网络模型,标准的是OSI七层网络模型,但实际使用中,都是根据TCP/IP构建的五层网络模型,或者将物理层和数据链路层合并后的四层网络模型,文章将以五层网络模型为基准。我们要讲的HTTP协议就是处在应用层的协议。

image.png

HTTPS其实就是在HTTP和TCP之间加了一层TLS/SSL协议。对于应用层协议HTTP来说,不需要太多改变,引入TLS/SSL协议就可以保证数据机密性和完整性。TSL/SSL协议就是利用密码学中的一系列算法来解决数据传输过程中的安全问题。它可以解决中间人攻击、端到端的身份验证,数据的机密性等问题。

对于客户端(如浏览器)来说,发送HTTPS请求就是连接服务器的443端口,将所有的HTTP数据传递给TLS/SSL协议,再由TLS/SSL协议将加密后的数据传递给传输层。

对于服务器来说,以Nginx为例,为了支持HTTPS,需要与默认监听80端口的HTTP进行区分,默认监听443端口。当接收到HTTPS请求后,Nginx先处理所有的TLS/SSL协议通信,再处理解密出的HTTP数据。

HTTPS为什么比HTTP更安全

HTTP协议为什么不安全?

这是因为HTTP的设计目的是数据传输和共享,根本就没有考虑安全问题。安全问题主要有三点:

数据没有加密

HTTP以明文传输,不会对信息进行加密,攻击者只要获取到这些明文,就能直接看到里面的用户隐私信息。那攻击者怎么获取呢?其实客户端在访问服务器的时候,客户端并没有直接跟服务器用一根网线连接着,客户端需要先把消息发送给路由器,路由器再发给与它连接的下一个节点设备。在你消息到达服务器之前,已经经过了很多个节点设备了。这些节点设备可以轻松地截获明文数据。

想知道你的消息会经过哪些节点?可以通过traceroute命令查看。这里以百度网址为例,第一跳中的192.168.1.1就是本机连接的路由器地址。( PS:要是想调路由器参数,又不想直接拿路由器看,就可以使用这种方式知道路由器的地址。也可以根据本机地址、网关和子网掩码进行计算 )。第7行和第9行是***,表明发出去的ICMP探测包没有响应,因为有些节点因为安全原因,直接不做响应。

traceroute.png

无法验证身份

虽然TCP保证了通信双方可以正确地传输数据,但是在HTTP应用中,客户端和服务器并不能互相验证身份。对于服务器来说,只要它接收的HTTP请求格式正确,就发送响应信息,客户端也是一样。HTTP模型由于限制非常少,实现HTTP应用可以很灵活,也产生了很多的中间设备,比如缓存代理服务器。但是没有身份验证也会有很多安全问题,比如想在淘宝上购物,你都不确定付款对象,怎么敢付款呢。

数据易篡改

HTTP数据在传输过程中经过了多个节点,这些节点都可以修改原始数据。对于服务器和客户端来说,都没有办法确认数据就是原始数据,只能无条件地信任接收到的数据。

HTTPS怎么解决这三个问题。

密钥加密数据

既然明文传输不安全,那么就把数据加密一下,变成密文传输嘛!问题是,怎么让与你通信的那一方解密你的密文呢?形象一点,数据的加密就像给数据加锁,虽然中间的节点设备可以接触到你的数据,但是它们没有钥匙解锁,不知道它的内容。数据到达对方那里后,对方再用钥匙解锁,成功拿到里面的数据。

对称加密.png

那么问题变成怎么让对方拿到钥匙。如果可以私下交易的话,确实可以把钥匙给到对方,可是这样的话互联网可能就无法发展到这么大规模了,想象一下你要怎么去跟那么多的网站去完成私下交易,然后去保存它们的钥匙。所以还是考虑直接通过网络传输。这时候就需要用到一点密码学的知识了。

常用的数据加密算法分为对称加密和非对称加密,对称说明加密解密都是使用相同的密钥,非对称说明加密和解密使用的是不同的密钥。

非对称加密

非对称加密算法中,经典的是RSA加密算法。RSA中有一对密钥对,分别是公钥和私钥。公钥加密的内容只有私钥才能解开,私钥加密的内容也只有公钥才能解开。RSA利用的是欧拉定理和大数计算的复杂性。RSA会先生成两个大质数p,q,需要用到的模数n就是pq的乘积,根据欧拉定理,计算n的最大质因数f(n) = (p-1)*(q-1)。再随机选取一个质数ee需要与f(n)互质,根据e*d = k*f(n) + 1求出解密需要用到的d,这里en是已知的,dk是未知的,实际就是求一个二元一次方程。那么可以解吗?这时候就要搬出欧拉老前辈的另外一个成果了-辗转相除法求最大公约数,它解决的一个问题就是ax + by = gcb(a, b)。前面要求ef(n)互质的原因就是要让它俩的最大公约数等于一。

至此,终于求出了用来解密的d。公钥里面的内容就是en,私钥里面的内容就是dn。具体的可以参考RSA算法原理。只有密钥长度足够长,就能保证仅仅通过en是无法解密d的,也就是说公钥公布出去后,别人也无法计算出私钥。

直接使用非对称加密是不是就可以保证通信数据的一个机密性了?

理论来讲是可行的,服务器生成一对RSA密钥,私钥自己保存,公钥直接明文传输给客户端。客户端也生成一对RSA密钥,私钥保存,公钥明文传输给服务器。之后的通信消息都用对方的公钥进行加密,然后用自己的私钥解密。但是 RSA的计算比较耗时,密钥一般都是1024位的,HTTP中的消息长度也比较长,做指数运算再取模,非常耗时,丧失了HTTP的快速响应能力。因此实际通信不采取这种方式,但是还是可以利用RSA算法来保障建立通信过程的机密性。

对称加密

在对称加密中,常用的是AES算法,AES算法是基于异或操作的,即XOR,位运算的速度非常快,同时也有密码学原理为安全背书,实际通信中多采用的是这种加密方式。 对称加密的特点是双方用来加解密的密钥相同,那么是肯定是不能直接把密钥传输给对方的,因此有一个客户端和服务器的密钥协商过程。

比较简单的一种密钥协商过程就是客户端直接生成一个会话密钥,利用服务器提供的CA证书中的RSA公钥进行加密传输,服务器用私钥解密出会话密钥后,双方就可以使用这个会话密钥进行通信了。这个过程没有协商,会话密钥的生成完全由客户端负责。这种方式的问题在于客户端不一定能保障生成的这个会话密钥的安全性,有较大可能被黑客猜测或者暴力破解。

实际的一个密钥协商过程会使用到DH算法,名称来自于两个作者的名字缩写。DH算法在进行密钥协商的时候,通信双方的任何一方无法独自计算出一个会话密钥,双方各自保存一部分关键信息,再将另外一部分信息告诉对方,双方有了全部信息才能共同计算出相同的会话密钥。

CA证书验证身份

当浏览器向服务器端发起连接请求时,服务器端会返回它的CA证书,证书主要包括签名、服务器实体信息和CA机构信息。其中的CA机构信息是一个证书链,根据标准,服务器应该发送完整的证书链(不包含根证书)。为了防止黑客劫持了消息,并且返回黑客伪造的证书链,浏览器需要确保每个证书(除了根证书)的签发者是它的上一级证书的使用者。

使用的证书验证方式是迭代签名验证,浏览器从服务器实体证书的上一级证书中获取公钥,校验服务器实体证书的签名是否正确,校验成功则继续往上迭代,直至找到根证书,否则证书校验失败,建立连接失败。

服务器也可以通过这种方式校验客户端的身份,但是通常没有这个必要。

image.png

MAC算法验证消息完整性

消息验证码(Message Authentication Code, MAC)算法可以验证消息是否遭到篡改,一般结合加密算法一起使用。那是不是可以直接使用Hash算法得到一个摘要值,将消息和摘要值一起发送过去,如下图所示进行验证。 image.png

表面上这个逻辑是没有问题的,但是由于Hash运算并没有使用密钥,黑客可以篡改消息后,再进行hash运算,把摘要值也篡改掉。接收方在验证时发现Hash后的摘要值与传递的摘要值一致。因此接收方还是无法验证消息是否被篡改了。

如何确保消息没有被篡改呢?还是需要用到对称加密,通信双方维护同一个密钥,用这个密钥来生成和验证消息验证码。MAC值 = mac(消息, 密钥)。以上用到的这些密钥,都是在客户端和服务器端建立连接时通过密钥协商过程一块生成的。

image.png

HTTPS的连接过程

下面将介绍在TCP三次握手之后,TLS/SSL层的一个连接过程。下面的流程基于目前常用的ECDHE密钥协商算法。不同的密钥协商算法的密钥协商过程会有所区别。

  • 首先是客户端向服务器发送Client Hello消息,在该消息中携带客户端生成的一个随机数,以及客户端支持的密码套件列表

    client hello.png

  • 然后服务器立即回复Server Hello消息,携带服务器端生成的一个随机数,并且根据客户端传递的密码套件列表,选择一个双方都支持的密码套件。完成密码套件的协商。

    server hello.png

  • 在服务器发送完Server Hello消息后,一般会立刻发送Server Certificate子消息,包含服务器的CA证书以及DH参数。同时使用Server Key Exchange消息,告诉客户端之后的通信将使用密钥通信。最后再加上Server Hello Done,说明服务器端的握手消息已经发送完毕。

    server key exchange.png

  • 客户端会验证服务器的CA证书,并且根据服务器传递的DH参数生成客户端公钥,将公钥传输给服务器,并且计算出将在之后通信中使用的预备主密钥,再利用之前选定的密码套件,得出通信需要的所有密钥。同时使用Server Key Exchange消息,告诉服务端之后的通信将使用密钥通信。最后携带Finished消息,对前面的握手消息进行验证,防止消息被篡改。

    change cipher spec.png

  • 服务端收到客户端传递的公钥,计算出预备主密钥,再利用之前选定的密码套件,得出通信需要的所有密钥。同时验证客户端的Finished消息,确保之前的握手消息没有被篡改。最后向客户端发送Finished消息,包含服务器握手消息的消息验证码。

    server finish.png

至此完成整个HTTPS中的加密连接部分,之后的通信都可以加密进行了。再用一个流程图简单总结。

image.png

HTTPS怎么防御中间人攻击

中间人攻击

当使用RSA或者DH密钥协商算法时,服务器需要提供一对密钥,中间人攻击就是服务器传递给客户端的公钥可能被攻击者替换。中间人在整个过程中,作为伪装的服务器端与客户端通信,由于它具有所需的所有密钥,它可以解密客户端的请求信息,然后再伪装成客户端与服务器通信,把客户端的请求发送给服务器端。

中间人攻击过程如下所示:

  • 客户端向服务器发起连接请求,中间人截获了这个请求。

  • 中间人自己生成一对RSA密钥,将公钥发送给客户端。

  • 中间人向服务器发送请求,服务器生成一对RSA密钥,将公钥发给中间人。

  • 在之后的过程中,客户端使用了中间人的RSA公钥加密消息,中间人顺利用私钥解密。获取明文后,再用服务器的公钥加密后,发送给服务器。从而控制了整个通信。

    image.png

在公开密钥算法中,所有的网络通信都会存在中间人攻击,解决问题的关键在于证书。在互相验证身份那一部分说到了证书的一个验证身份作用。证书中就包含了服务器身份的信息和服务器的公钥,并且使用数字签名技术,防止证书被篡改,再通过迭代验证的方式,确认证书的可靠性。

总结一下,之前是通过网络,服务器直接把公钥传给客户端。现在引入一个权威的CA机构,首先服务器向CA机构申请证书,然后在客户端请求连接时,服务器将证书发给客户端。客户端首先验证其中的服务器身份信息,是否是目前通信中的服务器。然后再根据CA证书链,验证证书的真实性。

因此如果中间人篡改了证书中的信息,客户端可以通过校验证书的数字签名发现。如果中间人把自己的CA证书发给客户端,客户端也可以验证其中的服务器信息与客户端想要通信的服务器不一致。

以上内容基于个人理解,如有错误敬请指出。

参考