HTTPS可能是我写这个系列的第一个坎,可以这么说,前面几篇的内容其实都是为了HTTPS服务的。在这个篇章中我希望能够按照自己的理解来把HTTPS协议完整地理清楚,HTTPS是如何通过那么多的环节以保证数据传输的安全性。
在写这篇文章的时候,我仅仅只是站在一个前端的角度上来看待这些东西,实际上很多内容其实也并不是写的很详细,我在简书上看到一篇写的很详细的博客,如果读者对于HTTPS的更加深层次的细节感兴趣,可以参考HTTPS加密原理。
首先讲讲HTTPS是什么?我们都知道HTTP协议是位于TCP协议的上层协议,在设计HTTP协议的同时,网景公司为其设计了一个安装套件,那就是SSL协议(后续演变成TLS协议),这个安全套件在TCP/IP协议族中位于HTTP协议下方,TCP协议上方,就是为了专门给HTTP协议的传输过程添加一层加密和解密的操作,以保证数据传输的相对安全,然后我们就将HTTP和TLS合称为HTTPS协议。
在之前的章节过程中,我们已经知道,非对称加密想对于非对称加密,虽然更加的安全,但是与之相对的,其更加更加的耗费时间。而TLS就是非常合理地同时兼顾了对称加密和非对称加密的优点,来构建一个安全的数据传输。我们都知道,非对称加密是基于一把密钥,成对的加密和解密算法来实现的,如果能保证密钥传输的安全性,那么非对称加密其实就能兼顾效率和安全。那么如果我们用非对称加密的方式来传输对称加密的密钥,就能解决对称加密密钥传输的安全性问题。如上,就是TLS层的作用,这里不禁要感叹一句,TCP/IP分层的作用在这里就能很明显的看出来了,我们可以非常低成本地在HTTP和TCP之间添加一层TLS协议,两层的逻辑可以彻底复用。
我们来正式讲讲HTTPS协议的整体流程(其实就是TLS构建流程),每一步都不多余,都有着十足的深意,这些都是互联网前辈的智慧的结晶(虽然我非常讨厌西方的政客,但是对于西方的著名学者,我一直十分尊敬)。
客户端向服务器发送约定俗称内容的请求,表示希望构建TLS连接,内容包含了客户端所支持的所有TLS协议,对称加密算法,非对称加密算法,Hash算法,以及一个客户端生成的一个随机数。
这步倒是没有什么好说的,先定规矩,总不能让服务器自行选定一个算法或者协议版本吧,万一客户端不支持呢?所以还是要由客户端指定可选择范围,然后服务器在其中进行挑选。如果客户端所提供的所有协议服务器都不支持,那么请求失败。至于随机数的作用,本文后续会谈到。
服务器接收到客户端所传过来的可选协议和算法范围,将选择结果和服务器所生成的一个随机数发送给客户端。这个随机数的作用也是在后续会进行说明。
服务器将证书机构所认证的证书发送给客户端,这个证书中就包含了服务器的公钥,同时为了保证公钥在传输过程中并没有被篡改。为了各方面的安全考虑,其实证书中并不仅仅包含服务器的公钥,还包含了很多其他用于辅助验证证书安全性的信息。
网络的传输环境是非常危险的,所以在传输证书的时候可能会被中间人篡改证书。所以在证书中会包含使用公钥基于证书机构公钥的数字签名,这样一来在客户端接收到服务器数据之后,可以通过证书中的证书机构公钥来验证公钥是否被篡改。
我们需要避免中间人将他自己的证书充当服务器证书返回的情况,在这种情况下,因为使用的是中间人的证书,所以所有加密信息对于中间人来说都失去了意义。所以我们就需要在证书中添加服务器的域名和地址,这样一来当我们接收到证书的时候就可以通过对比证书和服务器信息是否一致的方法来解决这个问题。
同样的道理,证书机构的公钥也存在着被篡改的风险。这里就存在着一个问题,如果一味使用另外一层证书机构来进行验证,这相当于陷入了死循环,因为我们永远不能保证公钥传输的安全性。
所以操作系统本身就会存储一些根证书,公钥机构最后都可以追溯到这些根证书。
客户端在接收到服务器发送过来的证书信息的时候,对其中的公钥进行验证。验证通过后,生成一个随机数pre-master,并通过公钥对其进行加密后发送到服务器端。服务器接收并解密后,此时客户端和服务器端都同时拥有客户端随机数,服务器随机数,pre-master随机数。
此时客户端会发送信息表示接下来将通过对称加密来传输信息,然后将前面环境互相交互的信息通过对称加密密钥发送给服务器端,来进行最后一次确认双方之前所沟通过的所有信息。
客户端和服务器会基于三个随机数(客户端随机数,服务器随机数,pre-master随机数)来生成master secter,包含:
为什么客户端随机需要使用这么多的密钥呢?明明我们之前说过,非对称加密不是只需要一个密钥就能进行加解密操作吗?
首先我们需要讲讲HMAC-Hash算法是什么?简单的来说,是包含密码的Hash算法。我们在传输数据的时候,虽然别人拿不到我们的对称密钥,但是不可避免的,他们依然可以随意更改我们所传输的信息,这样一来我们就需要类似数字签名的东西,这就是HMAC-Hash算法的作用。至于为什么需要带密码的Hash算法,这是因为不带密码的Hash算法就那么几种,中间人就可以逐个去试,尝试中了,就可以用那个Hash算法来对他们修改后的加密信息进行摘要(虽然中间人并不理解加密内容)。但是接收方接收到数据的时候就会认为该数据没有问题,然后直接使用中间人更改的数据。这个时候就需要到HMAC-hash算法来解决我们这里所遇到的问题了,即使Hash算法就那么几个,但是一旦与无数可能性的密码进行混用,那么中间人就无法模拟我们对于数据的摘要过程。
这是为了解决一个社会工程学问题,中间人在接收到我们所发送出来的加密信息后,虽然他们无法解密。但是如果客户端可服务器公用一把对称密钥,那么中间人可以将获取到的客户端数据直接放在服务器的返回结果里面,因为这个加密数据的确是正常加密的,所以客户端并不会察觉出异常。这就很尴尬了,所以就需要区分客户端可服务器端密钥从而解决这个问题。
至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好:
“不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。”
服务器在获取到pre-master key,并对客户端发送过来的全信息(SSL协议版本,加密套件,压缩算法等)进行校验后。服务器声明将开始通过master-key进行加密通信,并和客户端一样,会尝试发送一次全信息校验。客户端在接收到校验信息并验证后,HTTPS握手过程结束。
这个过程相当于是一次实战,前面的过程相当于仅仅是在理论上能实现数据的加密通信,实际行不行还是实际尝试操作一遍。客户端和服务器端分别进行一次校验且通过,就能说明信息传输在实际上也是可行的。