为什么需要HTTPS?什么是HTTPS?
我们知道HTTP有一个很大的特点就是明文传输,虽然这对于开发者而言是非常方便的。但同时对于那些不怀好意的黑客而已,明文传输数据简直是看不起它们(然说POST提交的数据时放在报体里看不到的,但是还是可以通过抓包工具窃取到)。显然,通过明文传输是及其不安全的。及其 容易收到中间人攻击。
为了防范这样一类攻击,我们不得已要引入新的加密方案,即 HTTPS。
HTTPS
并不是一个新的协议, 而是一个加强版的HTTP
。具体一点来说就是HTTP+TLS/SSL 协议。
原理:在HTTP和TCP之间建立一个中间层,当HTTP和TCP通信时并不像以前那样直接通信,直接经过一个中间层进行加密。将加密后的数据报传给TCP,响应的TCP必须将数据解密,才能传给上面的HTTP
。这个中间层也叫作安全层。安全层
的核心是对数据加解密
。、
接下来我们就来剖析一下HTTPS
的加解密是如何实现的。
HTTPS和HTTP区别
- HTTP是明文传输协议,HTTPS是有SSL + HTTP协议构建的可进行加密传输,身份认证的网络协议,比HTTP更加安全。
- HTTPS对搜索引擎更加友好,利于SEO优化。
- HTTPS标准端口443,HTTP标准端口80。
- HTTPS需要用到SSL证书,而HTTP不同。
HTTPS的主要作用:
- 对数据进行加密,并建立一条信息安全通道,来保证传输过程中数据的安全。
- 对网站服务器进行真实身份验证。
HTTPS工作原理
TLS/SSL 的功能实现主要依赖于三类基本算法:
散列函数
、对称加密
和非对称加密
,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
对称加密和非对称加密
概念
首先需要理解对称加密
和非对称加密
的概念,然后讨论两者应用后的效果如何。
加密和解密用同一个秘钥的加密方式叫做对称加密。Client客户端和Server端共用一套密钥,这样子的加密过程似乎很让人理解,但是随之会产生一些问题。
「问题一:」 WWW万维网有许许多多的客户端,不可能都用秘钥A进行信息加密,这样子很不合理,所以解决办法就是使用一个客户端使用一个密钥进行加密。
「问题二:「既然不同的客户端使用不同的密钥,那么」对称加密的密钥如何传输?」 那么解决的办法只能是**「一端生成一个秘钥,然后通过HTTP传输给另一端」**,那么这样子又会产生新的问题。
「问题三:」 这个传输密钥的过程,又如何保证加密?「如果被中间人拦截,密钥也会被获取,」 那么你会说对密钥再进行加密,那又怎么保存对密钥加密的过程,是加密的过程?
到这里,我们似乎想明白了,使用对称加密的方式,行不通,所以我们需要采用非对称加密👇
非对称加密
通过上面的分析,对称加密的方式行不通,那么我们来梳理一下非对称加密。采用的算法是RSA,所以在一些文章中也会看见**「传统RSA握手」,基于现在TLS主流版本是1.2,所以接下来梳理的是「TLS/1.2握手过程」**。
非对称加密中,我们需要明确的点是👇
- 有一对秘钥,「公钥」和「私钥」。
- 公钥加密的内容,只有私钥可以解开,私钥加密的内容,所有的公钥都可以解开,这里说的**「公钥都可以解开,指的是一对秘钥」**。
- 公钥可以发送给所有的客户端,私钥只保存在服务器端。
主要工作流程
梳理起来,可以把**「TLS 1.2 握手过程」**分为主要的五步👇
图片内容来自浪里行舟
步骤(1)
Client发起一个HTTPS请求,连接443端口。这个过程可以理解成是**「请求公钥的过程」**。
步骤(2)
Server端收到请求后,通过第三方机构私钥加密,会把数字证书(也可以认为是公钥证书)发送给Client。
步骤(3)
- 浏览器安装后会自动带一些权威第三方机构公钥,使用匹配的公钥对数字签名进行解密。
- 根据签名生成的规则对网站信息进行本地签名生成,然后两者比对。
- 通过比对两者签名,匹配则说明认证通过,不匹配则获取证书失败。
步骤(4)
在安全拿到**「服务器公钥」后,客户端Client随机生成一个「对称密钥」,使用「服务器公钥」(证书的公钥)加密这个「对称密钥」**,发送给Server(服务器)。
步骤(5)
Server(服务器)通过自己的私钥,对信息解密,至此得到了**「对称密钥」,此时两者都拥有了相同的「对称密钥」**。
接下来,就可以通过该对称密钥对传输的信息加密/解密啦,从上面图举个例子👇
- Client用户使用该**「对称密钥」**加密'明文内容B',发送给Server(服务器)
- Server使用该**「对称密钥」进行解密消息,得到明文内容B。 接下来考虑一个问题,「如果公钥被中间人拿到纂改怎么办呢?」**
以下图片来自leocoder
中间人获取公钥
「客户端可能拿到的公钥是假的,解决办法是什么呢?」
第三方认证
客户端无法识别传回公钥是中间人的,还是服务器的,这是问题的根本,我们是不是可以通过某种规范可以让客户端和服务器都遵循某种约定呢?那就是通过**「第三方认证的方式」**
在HTTPS中,通过 「证书」 + **「数字签名」**来解决这个问题。
这里唯一不同的是,假设对网站信息加密的算法是MD5,通过MD5加密后,「然后通过第三方机构的私钥再次对其加密,生成数字签名」。
这样子的话,数字证书包含有两个特别重要的信息👉**「某网站公钥+数字签名」**
我们再次假设中间人截取到服务器的公钥后,去替换成自己的公钥,因为有数字签名的存在,这样子客户端验证发现数字签名不匹配,这样子就防止中间人替换公钥的问题。
那么客户端是如何去对比两者数字签名的呢?
- 浏览器会去安装一些比较权威的第三方认证机构的公钥,比如VeriSign、Symantec以及GlobalSign等等。
- 验证数字签名的时候,会直接从本地拿到相应的第三方的公钥,对私钥加密后的数字签名进行解密得到真正的签名。
- 然后客户端利用签名生成规则进行签名生成,看两个签名是否匹配,如果匹配认证通过,不匹配则获取证书失败。
数字签名作用
数字签名:将网站的信息,通过特定的算法加密,比如MD5,加密之后,再通过服务器的私钥进行加密,形成**「加密后的数字签名」**。
第三方认证机构是一个公开的平台,中间人可以去获取。
如果没有数字签名的话,这样子可以就会有下面情况👇
从上面我们知道,如果**「只是对网站信息进行第三方机构私钥加密」**的话,还是会受到欺骗。
因为没有认证,所以中间人也向第三方认证机构进行申请,然后拦截后把所有的信息都替换成自己的,客户端仍然可以解密,并且无法判断这是服务器的还是中间人的,最后造成数据泄露。
「总结」
- HTTPS就是使用SSL/TLS协议进行加密传输
- 大致流程:
- 客户端拿到服务器的公钥(是正确的), 然后客户端随机生成一个**「对称加密的秘钥」,使用「该公钥」加密,传输给服务端,服务端再通过解密拿到该「对称秘钥」,后续的所有信息都通过该「对称秘钥」**进行加密解密,完成整个HTTPS的流程。
- 「第三方认证」,最重要的是**「数字签名」**,避免了获取的公钥是中间人的。
SSL 连接断开后如何恢复?
共有两种方法来恢复断开的 SSL 连接,一种是使用 session ID,一种是 session ticket。
通过session ID
使用 session ID 的方式,每一次的会话都有一个编号,当对话中断后,下一次重新连接时,只要客户端给出这个编号,服务器如果有这个编号的记录,那么双方就可以继续使用以前的秘钥,而不用重新生成一把。目前所有的浏览器都支持这一种方法。但是这种方法有一个缺点是,session ID 只能够存在一台服务器上,如果我们的请求通过负载平衡被转移到了其他的服务器上,那么就无法恢复对话。
通过session ticket
另一种方式是 session ticket 的方式,session ticket 是服务器在上一次对话中发送给客户的,这个 ticket 是加密的,只有服务器能够解密,里面包含了本次会话的信息,比如对话秘钥和加密方法等。这样不管我们的请求是否转移到其他的服务器上,当服务器将 ticket 解密以后,就能够获取上次对话的信息,就不用重新生成对话秘钥了。