深入理解 HTTPS 协议
本文能让还对 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
评论