前言:
本文首发于我的博客,欢迎进来玩,增加点击量。
本文的行文思路来自最近看的一本书《图解HTTP》,所有流程图均由自己在Excalidraw上原创,如需引用,请标明出处,也欢迎在本文评论区留言探讨,如果对您有帮助,请不要吝啬您的点赞和收藏~
背景
都4202年了,互联网如此发达的现在,我们经历过的网站和 Web 应用也越来越多,而细心的你可能会发现,几乎每个我们经常使用的网站都使用 HTTPS 协议传输数据,原因在于 HTTPS 相较于 HTTP 能够提供更加安全的服务。 浏览器对于使用 HTTP 协议的网站都会加上⚠︎标志表示数据传输不安全,而对于使用 HTTPS 协议的网站则会表示安全。 那么是什么让各个公司都纷纷选用 HTTPS 呢?这就不得不提 HTTP 协议在安全性方面上的三个缺点了:
HTTP的缺点:
- 通信使用明文(不加密),内容可能会被窃听。
- 不验证通信方的身份,通信方有可能遭遇伪装。
- 无法证明报文的完整性,有可能接收到的报文已遭篡改。
HTTPS来解决HTTP的安全性问题:
针对上文提到的三个方面的问题,我们的 HTTPS 协议堂堂诞生!那么它是怎么解决这三个问题的呢?
- 会被窃听?数据加密! : HTTPS 通信不再使用明文,而是使用加密后的密文。
- 会被伪装?数字证书! : HTTPS 通信双方通过数字证书机构(CA)颁布的数字证书来证明双方身份。
- 会被篡改?完整性保护! : HTTPS 通过摘要算法得到传输数据的摘要,如果数据被篡改,接收方算出的摘要将发生改变,接收方就知道传输数据已被篡改。
通过上面的介绍,我们也就可以回答这个经典问题了------------"什么是HTTPS?"
答:HTTP + 加密 + 认证 + 完整性保护 = HTTPS
HTTPS 是身披 SSL/TLS 外壳的 HTTP
其实 HTTPS 并非是应用层的一种新协议,只是在 HTTP 通信部分接口用 SSL (安全套接层)和 TLS (安全传输层协议)代替了而已:
- 通常情况下,HTTP 直接和 TCP 通信。
- 当使用 HTTPS 时,则变成 HTTP 先和 SSL/TLS 通信,再由 SSL 和 TCP 通信。所以也可以说:
HTTPS = SSL/TLS + HTTP
SSL/TLS 是世界上应用最为广泛的网络安全技术,在 HTTP 采用了他们之后,也就拥有了加密 + 认证 + 完整性保护这些功能。而且他们还不仅可以用在 HTTP 上,他们也可以用在任何需要加密的应用层协议上,如 SMTP 、Telnet 等
数据加密解决明文传输被窃听问题
在对 SSL/TLS 进行讲解之前,我们先来浅浅地了解一下加密算法们,如有错误请一定指出。 ps:从本章开始,我们都将通信双方假定为客户端和服务器,并且通常由客户端充当发送方,服务器充当接收方。
为了防止传输数据被黑客所窃听,客户端与服务器之间需要对数据进行加解密处理,如图所示,客户端 使用加密算法 将明文 转变为密文 ,而服务器 接收到密文 后,使用解密算法 将密文转变回明文 ,这样即使在通信中途密文被窃听了,黑客也无法获得有效的信息。
近代的加密方法中,加密算法是公开的,而密钥
却是保密的 。加密和解密都会用到密钥
,没有密钥
就无法对密文进行解密,反过来说,任何人只需要持有密钥
,就能进行解密了。我们一般将加密算法分为两大类:
- 对称加密:加密和解密时,使用相同的密钥。图中密钥A = 密钥B。
- 非对称加密:加密和解密时,使用不同的密钥。图中密钥A ≠ 密钥B。
对称加密
对称加密在加密和解密时,使用的是相同的密钥
。 凯撒加密是一种最简单且最广为人知的加密算法,它是一种替换加密的技术:明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。
如上图,每个字母都向后偏移了4个字母 的位置。那对于对称加密来说,这个偏移量 就是密钥
。
当然,凯撒加密过于简单了,肯定不算是行之有效的加密算法。 为了增加解密的难度,对称加密内部又细分为流加密 和分组加密两种类型,现在常用的对称加密算法有** DES 、3DES 、 AES 、RC4 **等。这里就不过多展开了。
对称加密的优缺点
- 优点:简单快捷、计算量小、加密速度快、加密效率高,一般是非对称加密算法的 100-10000 倍。
- 缺点:在数据传送前,发送方和接收方必须商定好秘钥 ,然后双方保存好秘钥。如果一方的秘钥被泄露,那么加密信息也就不安全了 。所以在商定阶段 ,就很容易泄露
密钥
。
非对称加密
对称加密在加密和解密时,使用的是一对 不同的密钥
,分别是公开密钥(简称公钥
)和私有密钥(简称私钥
)
私钥
只能由一方安全保管,不能泄露。而公钥
则可以发给任何请求它的人。- 非对称加密使用这对密钥中的一个进行加密 ,另一个则用来解密。
如图所示,在商定阶段,客户端请求服务器的公钥,在数据传输节点,客户端用公钥加密,服务器用私钥解密。与对称加密不同的是,即使在商定阶段公钥被窃听了,黑客也几乎不可能根据公钥和密文解出明文。现在常用的非对称加密算法有:**RSA 、ECC(移动设备用)、Diffie-Hellman 、El Gamal 、DSA(数字签名用)**等。
非对称加密的优缺点
- 优点:安全性更好,即使公钥暴露了也无所谓。
- 缺点:存在大量的指数运算,加密和解密速度都非常慢,只适合对少量数据进行加密。
HTTPS 采用混合加密
前文已经介绍过了,如果使用对称加密,密钥
容易泄露。如果使用不对称加密,密钥
安全了,但速度可太慢了,完全满足不了当今网络传输数据量的需要。所以机智的 HTTPS 充分利用了两者各自的优势,采用了混合加密的方法:
- 在商定阶段 使用非对称加密 :用
公钥
加密,私钥
解密,确保下个阶段的密钥
安全到达双方。 - 在传输数据阶段 使用对称加密 :在确保
密钥
安全的情况下,就可以大胆使用对称加密提速了。 也就是说,用非对称加密算法传输密钥,用对称加密算法传输实际数据 。为了方便描述,我们将商定阶段传输的密钥
称为共享密钥
。
数字证书解决 HTTP 通信方有可能遭遇伪装问题
只有混合加密还不够
在前文中,我们已经了解了混合加密
的方式和共享密钥
的存在。但是万一客户端和服务器之间,有黑客伪装成中间者(如 DNS服务器),即使是混合加密
也会让密文加密的真实内容暴露,如图:
- 客户端发送的请求被黑客伪装的 DNS服务器 劫持,客户端向中间者请求
公钥1
。 - 中间者正常转发请求
公钥1
的请求到服务器。 - 服务器响应
公钥1
给中间者。 - 中间者假装自己是服务器,给客户端响应原属于自己的
公钥2
。 - 客户端用
公钥2
加密接下来要传输的共享密钥
,向服务器(其实是中间者)发出。 - 中间者使用自己的
私钥2
解密得到共享密钥
,至此共享密钥已经泄露。 - 中间者使用先前获得的
公钥1
加密共享密钥
。 - 中间者将加密后的
共享密钥
发至服务器。 - 服务器用
私钥1
解密后也得到共享密钥
。 - 此后客户端和服务器之间再用
共享密钥
加密传输数据,由于共享密钥
泄露,中间者将清清楚楚地知道传输内容 ,也就能随心所欲地篡改 和窃听了。
那么有没有办法能让客户端在第4步 得到公钥
的时候,证明它是来自服务器而不是其他人的呢? 答:有!解决办法就是1数字证书`!
数字证书
如果有人突然问你一个问题,如何证明你是你自己呢?
,那当然是靠身份证
了。对于网站也是一样,如何证明你的网站是合法的而不是黑客假冒的呢?
,这个时候就要靠数字证书
啦。 就如同身份证
的有效性是由国家权威机构
保证的一样,我们网站的数字证书
也需要权威的第三方机构
来保证书的有效性,这样的机构我们就称为数字证书机构
(简称CA机构
或CA
)。 所以我们目前给自己网站申请使用 HTTPS 协议的时候,都需要去CA
申请一份数字证书
。申请数字证书
需要服务器提供申请者、域名、公钥
等信息。
有了数字证书
,当浏览器向目标网站服务器发起请求时,服务器只需要把数字证书
返回给浏览器就能证明自己的合法性了。但是还不够,如果数字证书
在传输过程中被挟持并篡改了,还是会出现中间者问题。
带数字签名的数字证书
为了解决上述问题,CA机构
机智地使用了数字签名
:CA机构
在向网站颁布数字证书
之前,会在数字证书
上签名,这个签名相当于------------来自CA机构的私钥
加密后的数字证书摘要
。而这个被加密后的摘要
,在客户端浏览器中可以通过CA机构的公钥
和摘要算法
验证其有效性。如图:
- 网站服务器用自己的
公钥1
向CA机构
申请数字证书
。 CA机构
通过审核之后,会生成一份证书明文
,其中就包括了申请者的公钥
和其他信息。CA机构
利用一种摘要算法
对证书明文
进行摘要,得到证书摘要
。CA机构
用自己的私钥
加密证书摘要
得到数字签名
CA机构
将数字签名
与证书明文
合并,得到数字证书
,并颁布给对应网站服务器。- 客户端向服务器请求得到
数字证书
后,自行在浏览器上验证。
浏览器是怎么验证数字证书的呢?如图:
- 浏览器拿到
数字证书
之后,将其拆分为数字签名
与证书明文
。 - 用
CA机构公钥
解密数字签名
,得到证书摘要1
。 - 用
CA机构同种摘要算法
处理证书明文
,得到证书摘要2
。 - 比较以上两次操作得到的摘要,如果相同,则证明有效。反之则无效。
而 Chrome 浏览器一旦发现证书无效或者证书过期,则会提示如下警告:
至此,HTTP 通信方有可能遭遇伪装的问题也就解决了!
摘要算法解决传输数据被篡改问题
摘要算法又称哈希算法、散列算法。摘要
也称哈希值,表示输入任意长度的数据,都会输出固定长度的数据。
摘要算法具有以下特点:
- 压缩性:任意长度的数据,计算出的
摘要
长度都是固定的(如 MD5(32) 结果长度固定为128位)。 - 容易计算:从原数据计算出
摘要
很容易,消耗时间短。 - 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的
摘要
都有很大区别。即:不同输入,绝大概率 计算出不同的摘要
。 - 同源性:相同的输入,相同的摘要算法,一定 会计算出相同的
摘要
。 - 强抗碰撞:已知原数据和其
摘要
,想通过组合碰撞找到一个具有相同摘要
的数据(即破解原数据)是非常困难的。 - 不可逆性:无法根据
摘要
反推出原文。
现在常用的摘要算法有:MD5、SHA1 、SHA256 、HAMC 、CMAC 等。其中 MD5 和 SHA1 都已经被破解了,要注意使用。
在数据传输中加入摘要
在 HTTPS 的数据传输过程中,客户端会将明文
与通过明文生成的摘要1
一齐发送至服务器,服务器收到明文
后,会用与客户端相同的摘要算法 生成摘要2
,比较以上两个摘要
,就可以看出明文
是否有被篡改过了。 上一句提到的"相同的摘要算法"是在通信双方 TLS 握手
阶段商定的,我们之后会说到。
引入 HMAC 防止摘要也被篡改
通过上面的做法,我们大致可以防止明文被篡改了,但这样做还是存在一个问题:如果黑客在篡改明文
的同时,也篡改了摘要
,这要怎么办呢?
这个时候,所以 HTTPS 还引入一种优化方案:HMAC(消息认证码) 。定义 HMAC 需要一个散列函数(即 MD5 SHA 之类)和一个密钥(比如一个随机数密钥 ),也就是说此时摘要算法的输入变成了两部分:数据明文
+ 随机数密钥
。需要注意的一点是,这个随机数密钥
只能有通信双方知道,黑客是不可能知道的,所以该随机数密钥
应该在商定阶段
被确定。如图:由于黑客不可能这个随机数密钥
,篡改的摘要3
也就不正确了。
小结,引出 SSL/TLS 握手
说了这么多,让我们来总结一下 HTTPS 需要用到算法/密钥总共有什么吧:
- 传输数据,需要对称加密算法 和
共享密钥
。 - 传输
共享密钥
需要非对称加密算法。 - 防止被伪装身份,需要数字证书 。(数字证书中能取出
服务器公钥
) - 保证报文完整性,需要摘要算法。
- 防止摘要被篡改,需要 HMAC 的随机数密钥。
有这么多东西需要被商定 ,这些工作都是靠谁完成的呢?诶,这些全都是由 SSL/TLS
完成的。那 SSL/TLS
又是怎么完成商定的呢?我们继续往下看。
SSL/TLS 发展进程
SSL
(Secure Sockets Layer) 是网景公司(Netscape)设计的主要用于 Web 的安全传输协议,这种协议在 Web 上获得了广泛的应用。以下是摘取自权威文档部分发展历史:
- 1996 年,SSL3.0 问世,得到大规模应用(已于 2015 年弃用)。
- 1999 年,SSL3.1 被标准化,更新为 TLS1.0(Transport Layer Security)。所以有,TLS1.0 = SSL3.1。
- 现在主流的版本是 TLS1.2(2008 年发布)。
- 未来,可能是 TLS1.3 的时代(2018 年发布)。
所以在之后的篇章中,我统一用
TLS
称呼SSL/TLS
协议和TLS1.2
协议。 后文出现的WireShark
抓包图片,需要下载WireShark
抓包并进行环境变量配置。
TLS 握手
上文已经说过了,HTTPS = HTTP + TLS 。 这里的 TLS
指的就是 TLS 握手
,它类似于 TCP 三次握手 。 在 TLS 握手
的过程中,通信双方交换消息以相互确认对方身份 ,并确立它们所要使用的 TLS 版本 、密码套件等等。
TLS 四次握手
发生在 TCP 三次握手
之后,HTTP 传输数据
之前。
第一次握手
1. Client Hello
Client Hello
是 TLS 四次握手
的第一个步骤,表示客户端向服务端发起了一个 TLS握手
请求,本次报文内容主要包括:
- 客户端支持的 TLS 版本 :客户端将自己所支持的
TLS
版本告知服务器,服务器做选择,如TLS 1.2
。 - 客户端随机数 :客户端随机生成的一个数,后续用来生成
共享密钥
和随机数密钥
。 - 客户端支持的加密套件 (Cipher suite ):客户端将自己支持的所有 加密套件做成列表告知服务器,服务器做选择,每个加密套件格式如下图:
第二次握手
2. Server Hello
服务器接收到 "Client Hello"
后,也进入TLS握手
流程,连着发送三个响应客户端的响应,第一个响应内容主要包括:
- 服务器选择的 TLS 版本 :服务器做出选择。
- 服务器随机数 :服务器随机生成的一个数,后续用来生成
共享密钥
和随机数密钥
。 - 服务器选择的加密套件 :服务器选择一个加密套件。
3. Certificate
服务器主持的第二次握手
过程中,还需要将包含服务器公钥
的数字证书
也发给客户端。
4. Server Hello Done
服务器发送此报文表示:自己已将所有预计商定的信息都发送完毕,第二次握手
结束。
第二次握手补充: Server Key Exchange
经提醒,如果服务器数字证书
没有足够的信息,不能让客户端完成pre-master
的密钥交换时,服务器会在 "Server Hello"
后,立即发送 "Server Key Exchange"
来补充信息, 主要是面向安全的几种密钥协商算法,列表如下:
- DHE_DSS
- DHE_RSA
- DH_anon
- ECDHE_ECDSA
- ECDHE_RSA
- ECDH_anon
第三次握手(需先验证数字证书
)
客户端收到服务器第二次握手
的信息后,会验证其数字证书
是否合法 ,如果证书合法,则进行第三次握手
。
5. Client Key Exchange
证书验证通过之后,客户端会生成pre-master
(前主密钥),不过会因不同的算法套件而有差异:
ECDHE
会传递一个随机生成的client params
。RSA
会随机生成pre-master
,然后用服务器公钥
加密后传递。
此时,客户端已经拥有:客户端随机数
,服务器随机数
,pre-master
或client params
,客户端将用此三者结合生成master secret
(主密钥),master secret
会被用来生成共享密钥
和随机数密钥
。
6. Change Cipher Spec
通知服务器,后续客户端发送的消息都将采用对称加密通信。
7. Finished
客户端会将此前生成的共享密钥
和随机数密钥
用在此处加密报文,送给服务器解读。如果服务器能解读,说明此前的商定阶段成功完成。 至此,第三次握手
结束。
第四次握手
在第四次握手
之前,服务器需要从之前第5步:"Client Key Exchange"
中,提取出来client params
或用服务器私钥
解密得到pre-master
。 此时,服务器也拥有:客户端随机数
,服务器随机数
,pre-master
或client params
。那它也能将三者结合生成和客户端一模一样 的master secret
,再用它生成共享密钥
和随机数密钥
。
然后服务器进入第四次握手
流程,它也会执行和客户端第三次握手
时一模一样的操作,将加密报文送给客户端解读。如果客户端能解读,说明 TLS 四次握手
全阶段完成。
8. Change Cipher Spec
与第6步一致。
9. Finished
与第7步一致。
TLS握手结束
至此 TLS 握手
过程圆满结束!如果还看不明白的同学,建议重看上面每一步的解释并结合着这张图慢慢理解,相信你们可以的。其实不难看出,TLS 握手
的整个流程就是为了:
- 确定所使用的TLS版本,加密算法,摘要算法。
- 确保通信双方能安全 地生成一模一样的
共享密钥
和随机数密钥
。
总结:
写这篇文章的主要原因是,最近在看书时发现自己以前整理的 HTTPS 笔记真的非常片面,所以才诞生了系统地重新整理一遍 HTTPS 知识的念头。当然,本篇文章的内容也仅够科普使用,如果想要更深入了解 HTTPS ,可以去详细读读《HTTPS权威指南》。
仅当抛砖引玉,有错误请指出!有帮助请不要吝啬你们的点赞和收藏~