阅读 2337

深入理解HTTPS协议

为什么需要深入理解HTTPS协议

因为目前越来越多的网站或者app已经全面接入HTTPS,APPLE官方也建议APP全面使用HTTPS,何况国内这种节操都没有喜欢劫持网络请求的运营商在,没有HTTPS 实在是毁用户体验。多数人都是只知道HTTPS是基于HTTP的,有加密功能,但不知道这个是怎么实现的,相信我,作为一个开发者你以后始终会碰到HTTPS的相关问题,从源头弄懂这份协议很有必要。

阅读本文需要什么基础

最好对HTTP协议有所了解,不需要太透彻,但是基本概念要知道。如果能懂一些TCP/IP 方面的东西就更好了。

阅读本文能有什么好处

本文能让还对HTTPS懵懵懂懂的你,彻底从头到尾明白这份协议到底是怎么一回事。太多的相关文章只告诉了你这份协议怎么做, 却没告诉你为什么要这么做,以及验证这份协议到底是不是真的这么做的一个探索的过程。

从Wireshark复习TCP三次握手的重要性

还不知道TCP三次握手的同学,可以先自行搜索一下相关知识。这里为什么要复习tcp三次握手,因为HTTP链接是在这之上的, 任何一个http链接,都需要tcp的三次握手的过程,https下面的加密层其实和这个有异曲同工之妙。况且通过这次复习,我们还能学习下wireshark的相关知识。掌握wireshark对我们弄懂HTTPS至关重要。 简单贴一下,tcp 三次握手的流程:

到这里,相信有基础的同学应该都回忆起来这是怎么回事了。我不做过多解释,直接上工具wireshark。 我们随便输入一个http的地址(注意不要访问https的,有些网站比如bat这种大网站你输入http也会直接转成https所以我们还是 随便选个小网站确保是http的)

然后明显能看出来是吧,有三次tcp的过程,然后才是http的链接。

细致分析下这个三次握手的过程:

第一次握手:主机A发送位码为syn=1,随机产生seq number=0的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=0的包

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

完成三次握手,主机A与主机B开始传送数据。

有的人可能会问,seq number不是随机number吗,你这里怎么都是0啊。

点开详细:

这里面告诉你了 是相对数字,方便你看。你当然可以选择看实际数字 加深理解

在这个里面把相对数字选项勾选掉,就可以看到真实的seq number了

怎么样这里是不是就豁然开朗了,当然明白就好,平时最好还是勾选这个选项这样理解的快一点。

对称加密和非对称加密

这也是理解https的重要基础之一。这里涉及到很多复杂的算法,我并不精通算法和密码学,所以这里不讲的太细。你们只要知道个大概即可:

对称加密:加密和解密都用一个密钥,有点是速度快。缺点吗,显而易见的是 双方要用这个通信的话 必须得把密钥告知对方, 但是这个密钥一旦被截获了,就可以随便decode出来明文。实际上不够安全。

非对称加密:有一对密钥,即有公钥也有私钥。公钥随便发,私钥不会发出去 各自保管。用一个加密的话,解密就只能用另外一个。比如你向银行请求一个公钥,银行把公钥发给你,你用公钥加密一条信息以后 再发给银行,然后银行用私钥解密信息。这个过程就算有人拿到公钥,但是因为非对称加密用一个加密 只能用另外一个解密,所以 拿到这公钥也没用,因为无法使用公钥解密,能解密的私钥还在银行那里,银行当然不会传出去,所以非对称加密很安全。 但是这种非对称加密非常消耗资源,速度极慢,所以要有限使用。不能无节制使用。

HASH加密算法:这个就好像MD5这样的加密方式,是不可逆的。

确保安全通信的三个原则

A.数据内容的加密

这个很好理解是吧,敏感信息肯定要加密的,明文传输等于自杀。不过多解释了。

B.通讯双方的身份校验

这个很多人不理解,这是啥意思,按道理说我们用非对称加密应该就完美了啊。但是谨记我们的数据包不是从A直接到B的。 中间要经过无数次的路由器转发等等,这个中间一旦有人截获了我们的数据包,换成自己的数据包,就很危险了。 所以我们还需要一种机制能校验通讯双方的身份。确保我是在和我老婆说话 而不是在我和丈母娘说话。

C.数据内容的完整性

这个也不是很容易理解,按道理说TCP是能保证数据有序完整的到达对方的。但是不要忘记中间我们经过的无数次路由器转发, 可能被劫持,被劫持以后可能会对数据包进行篡改,这个时候我们需要一种机制保护我们的数据不被篡改,即使被篡改 也能被我们察觉,确保我对我老婆写的信能完整的让我老婆看到,而不是只看到一半。

https的设计思路

根据前面我们阐述的加密算法和安全通信三原则,为了保证我们的通信能够安全进行,可以试想出一种流程来保证通信安全:

  • 服务器为每个客户端生成一个公钥,将公钥发送给客户端
  • 客户端选择一个加密算法,然后用公钥加密以后发送给服务器
  • 服务器收到这个公钥加密后的算法以后拿自己的私钥解密,然后就知道这个加密算法是哪个了。今后就一直用这个算法通信。

目前来看,这个思路是不是很完美。公钥即使被中间人截获以后也没用,因为拿到公钥也解密不出来到底双方是用哪种算法加密的。 但有个重大缺陷:

中间人可以将服务器发送的公钥包进行掉包,客户端怎么知道这个公钥是真的服务器发送的还是假的中间人给的非法公钥呢?

可以看这张图,基本上中间人攻击就是这个图所示的意思。

解决中间人攻击问题

这个问题的解决办法其实也很粗暴:

  • 使用权威的第三方机构也就是CA向安全的服务器颁发证书。来证明这台服务器的合法性。
  • 服务器通过这个证书来把自己的公钥加密以后发给客户端
  • 客户端收到这个加密后的公钥以后 ,就用第三方机构的公钥 把这个服务器返回的加密后的公钥 解密 从而得到真正的服务器 的公钥

带来的问题:

客户端到哪去取第三方公钥?

  • 你的操作系统或者浏览器自身就带有权威机构的第三方公钥

  • 如果中间人得到CA认证怎么办?这种情况基本没办法处理,如果发生,那么这个CA下面所有的证书都被认为非法了。所以 CA审核也很严格啊

CA证书是收费的啊,我不想交钱咋办呢

可以自己制作证书,然后把这个证书的公钥放在客户端(例如app的安装目录下),这样app只要使用自己的证书公钥即可 解密了,不需要使用系统的。但是这样带来的问题是,如果有人获取到了你这个公钥证书咋办? 数字签名认证算法即可保证此类问题,其实简单来说就是服务器和客户端事先约定好一种加密规则即可,就可以得知是否被篡改。 这部分由于不是重点,暂时不讲的太细,只要知道有这么个事即可。实际上你弄懂整个https以后这个地方就自然而然也能 想明白了。

有了上述基础,我们终于可以按照科班的方式来理解HTTPS真正的流程

为什么HTTPS的流程要放在最后再讲,因为放在前面讲,根本不会理解为啥要这么做,很快就会忘记。有了前面的基础 再来看这个流程,就会恍然大悟。

  • 先看蓝色的部分,可以看出来,这是tcp链接。所以https的加密层也是在tcp之上的。

  • 客户端首先发起clientHello消息。包含一个客户端随机生成的random1 数字,客户端支持的加密算法,以及SSL信息。

  • 服务器收到客户端的clientHello消息以后,取出客户端法发来的random1数字,并且取出客户端发来的支持的加密算法, 然后选出一个加密算法,并生成一个随机数random2,发送给客户端serverhello

  • 让客户端对服务器进行身份校验,服务端通过将自己的公钥通过数字证书的方式发送给客户端

  • 客户端收到服务端传来的证书后,先从 CA 验证该证书的合法性,验证通过后取出证书中的服务端公钥,再生成一个随机数 Random3,再用服务端公钥非对称加密 Random3 生成 PreMaster Key。并将PreMaster Key发送到服务端,服务端通过私钥将PreMaster Key解密获取到Random3,此时客户端和服务器都持有三个随机数Random1 Random2 Random3,双方在通过这三个随即书生成一个对称加密的密钥.双方根据这三个随即数经过相同的算法生成一个密钥,而以后应用层传输的数据都使用这套密钥进行加密.

  • Change Cipher Spec:告诉客户端以后的通讯都使用这一套密钥来进行.

最后ApplicationData 全部使用对称加密的原因就是非对称加密太卡,对称加密不影响性能。所以实际上也看的出来 HTTPS的真正目的就是保证对称加密的 密钥不被破解,不被替换,不被中间人攻击,如果发生了上述情况,那么HTTPS的加密 层也能获知,避免发生事故。

最后我们用WireShark再来还原一次HTTPS的交互过程把

目标访问地址就用github吧。 抓出来是这样的。

注意看tlsv1的就可以了这个就是加密层。

下面就来逐步分析

  • ClientHello

  • severHello

注意到这里服务器和客户端就有2个随机数了。并且加密算法也确定了。

  • severHelloDone

这部分主要是发送证书信息的 点开以后 证书的详细信息都能看到 另外serverhellodone的意思就是服务器的工作都完毕了。

  • 来看看第四步,客户端-->服务端 到底做了什么

可以看出来这里一共有三个步骤,我们来依次分析 这三次动作都做了什么

Client Key Exchange

服务器收到这个random3的加密信息以后,用自己的私钥解密,这样服务器和客户端就共同拥有了random 123 3组随机数,然后用这三组数据生成一个密钥,这个密钥就是后面我们applicationdata交互时使用的对称加密的密钥了

  • 第五步 服务端-客户端

  • 最后看看第六步也是最后一步,传输数据层。

new session ticket是啥意思

这个session ticket就是服务器最后一步的时候传给客户端的一个数据。 这个加密数据客户端收到以后就可以保存下来,这样下一次再请求https的 时候,就可以把这个session ticket发过去,这样可以省很多握手的时间和 资源消耗。(前面我们分析的4-5步其实已经相当复杂了,尤其是非对称加密对服务端的资源消耗相当之大)

实际上对于多数浏览器来说,指向同一个域名的https连接,我们都会有意识的让第一个https连接完成握手之后再连接第n个 https。因为这样 后续的https 就可以携带相关信息,可以省很多资源

这个ticket实际上就有点类似cookie。

在笔者的这次访问chrome-gitub的过程中,浏览器并没有使用ticket技术 而是使用的seession id技术:

sessionid 实际上作用和ticket差不多,但是sessionid 无法做到服务器之间同步,毕竟id 存在服务器内存中,负载均衡带来的状态机同步是一个大问题。

总结

其实HTTPS总结起来就是3次tcp握手-5次TLS握手。搞清楚每一步做什么, 用的是对称加密还是非对称加密,整个流程就肯定能搞清楚了。 以后遇到类似的问题就能快速定位优化了。甚至抓取BAT的HTTPS接口 数据都不是难事。如果有需要的话大家就在下方留言,我会尽快 教大家如何抓取bat的https接口数据 并且decode出明文。

关注下面的标签,发现更多相似文章
评论

查看更多 >