HTTPS原理

整理自:看完还不懂HTTPS我直播吃翔

前言

HTTPS(全称:HyperText Transfer Protocol over Secure Socket Layer),其实 HTTPS 并不是一个新鲜协议,Google 很早就开始启用了,初衷是为了保证数据安全。 近两年,Google、Baidu、Facebook 等这样的互联网巨头,不谋而合地开始大力推行 HTTPS, 国内外的大型互联网公司很多也都已经启用了全站 HTTPS,这也是未来互联网发展的趋势。
为鼓励全球网站的 HTTPS 实现,一些互联网公司都提出了自己的要求:

  • Google 已调整搜索引擎算法,让采用 HTTPS 的网站在搜索中排名更靠前;
  • 从 2017 年开始,Chrome 浏览器已把采用 HTTP 协议的网站标记为不安全网站;
  • 苹果要求 2017 年 App Store 中的所有应用都必须使用 HTTPS 加密连接;
  • 当前国内炒的很火热的微信小程序也要求必须使用 HTTPS 协议;
  • 新一代的 HTTP/2 协议的支持需以 HTTPS 为基础。

因此,想必在不久的将来,全网 HTTPS 势在必行。

为什么需要HTTPS

HTTP 是非常常见的应用层协议,是超文本传输协议的简称,其传输的内容都是明文的。在这个混乱的世界,明文传输信息想想就可怕,网络“小混混”的手段远比我们这些凡人高明得多,他们有一万种方式劫持,篡改我们的数据。对于一个网站或者服务,如果你给你的用户两个选择:

  1. 通讯数据明文传输,速度快;
  2. 通讯数据加密传输,但是速度可能会稍微慢一点。

我想,只要脑袋没有长歪的用户都宁愿牺牲一点速度去换取数据传输的安全。
这样,HTTPS 的存在就具备了合理性,HTTPS 中的 s 表示 SSL 或者 TLS ,就是在原 HTTP 的基础上加上一层用于数据加密、解密、身份认证的安全层。
httpvshttps
如上图所示 HTTPS 相比 HTTP 多了一层 SSL/TLS
SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。
TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999 年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0 和 TLS1.0 由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是 TLS 1.1、TLS 1.2。

一层层揭开HTTPS神秘面纱

虽然要层层渐进,但是我们不妨先奉上刚画好的还热乎着的 HTTPS 通信完整流程图:
449687-4e2ec739a1487779
从上图可以看到,右边有一堆钥匙,一看到钥匙我们就能想到这个过程免不了加密。另外,那些钥匙长得还不一样,有些只有一把,有些是一对,嗯,是的,你看得真仔细。
好的,扯远了,现在开始层层渐进。

第一层(安全传输数据)

假如我们要实现一个功能:一个用户 A 给一个用户 B 发消息,但是要保证这个消息的内容只能被 A 和 B 知道,其他的无论是墨渊上神还是太上老君都没办法破解或者篡改消息的内容。
449687-8883dac16e78293f
由于消息不想被其他人看到,所以我们自然而然就会想到为消息加密,并且只有 A 和 B 才有解密的密钥。这里需要考虑几点:

  1. 使用什么加密方式?
  2. 密钥怎么告知对方?

对于第一个问题,加密算法分为两类:对称加密和非对称加密,这里我们选择对称机密,原因有如下几个:

  1. 对称加密速度快,加密时 CPU 资源消耗少;
  2. 非对称加密对待加密的数据的长度有比较严格的要求,不能太长,但是实际中消息可能会很长(比如你给你女朋友发情书),因此非对称加密就满足不了。

对于第二个问题,这是导致整个 HTTPS 通信过程很复杂的根本原因。
如果 A 或 B 直接把他们之间用于解密的密钥通过互联网传输给对方,那一旦密钥被第三者劫持,第三者就能正确解密 A, B 之间的通信数据。

第二层(安全传输密钥)

通过第一层的描述,第二层需要解决的问题是:安全地传输A,B之间用于解密数据的密钥。
449687-e906fa0e6c48c3ce
因为如果传输过程中这把密钥被第三者拿到了,就能解密传通信数据,所以,这把密钥必须得加密,就算第三者劫持到这把加密过的密钥,他也不能解密,得到真正的密钥。
这里有一个问题,那要用什么方式加密这把密钥呢?如果使用对称加密,那这个对称加密的密钥又怎么安全地告诉对方呢?完了,陷入死循环了…. 所以,一定不能用对称加密。
那就是用非对称加密咯,那如何应用非对称加密来加密那把密钥呢?
考虑如下方式:
449687-2426a0150c6c0279

  1. 客户端: 我要发起 HTTPS 请求,麻烦给我一个非对称加密的公钥;
  2. 服务器: (生成一对非对称加密的密钥对,然后把公钥发给客户端),接着,这是公钥;
  3. 客户端:(收到公钥,生成一个随机数,作为上图中那一把密钥,用刚才收到的公钥加密这个密钥,然后发给服务器)这是我刚生成的加密过的密钥;
  4. 服务器:(收到加密后的密钥,用本地的第一步自己生成的非对称加密的私钥解密,得到真正的密钥)。

现在,客户端和服务器都知道了这把密钥,就能愉快地用这个密钥对称加密数据…
分析一下上面步骤的可行性:
上述步骤中最终用于加密数据的密钥是客户端生成并且用公钥加密之后传给服务器的,因为私钥只有服务器才有,所以也就只有服务器才能解开客户端上报的密钥;
要保证传输的密钥只能被服务器解密,就得保证用于加密密钥的公钥一定是服务器下发的,绝对不可能被第三方篡改过;
因为还可能存在一种“中间人攻击”的情况,如下图:
449687-f23fb6905efc4867-new
这种情况下,客户端和服务器之间通信的数据就完全被坏人破解了。

第三层(安全传输公钥)

从上一层可以知道,要保证数据的安全,就必须得保证服务器给客户端下发的公钥是真正的公钥,而不是中间人伪造的公钥。那怎么保证呢?
那就得引入数字证书了,数字证书是服务器主动去权威机构申请的,证书中包含了上一个图中的加密过的 A 公钥和权威机构的信息,所以服务器只需要给客户端下发数字证书即可。现在流程图如下:
449687-2c0fe3a7fbd6b3ad
那数字证书中的 A 公钥是如何加密的呢?
答案是非对称加密,只不过这里是使用只有权威机构自己才有的私钥加密。
等一下,既然 A 公钥被权威机构的私钥加密了,那客户端收到证书之后怎么解密证书中的 A 公钥呢?需要有权威机构的公钥才能解密啊!那这个权威机构的公钥又是怎么安全地传输给客户端的呢?感觉进入了鸡生蛋,蛋生鸡的悖论了。
别慌,答案是权威机构的公钥不需要传输,因为权威机构会和主流的浏览器或操作系统合作,将他们的公钥内置在浏览器或操作系统环境中。客户端收到证书之后,只需要从证书中找到权威机构的信息,并从本地环境中找到权威机构的公钥,就能正确解密 A 公钥。
这样就绝对安全了吗?既然权威技能能给服务器签发数字证书,那为什么就不可能给中间人签发数字证书呢?毕竟赚钱的生意权威机构也不会拒绝的呀。
试想一下:
服务器给客户端下发数字证书时证书被中间人劫持了,中间人将服务器的证书替换成自己的证书下发给客户端,客户端收到之后能够通过权威机构的公钥解密证书内容(因为中间人的证书也是权威机构私钥加密的),从而获取公钥,但是,这里的公钥并不是服务器原本的 A 公钥,而是中间人自己证书中的 B 公钥。从第二层可知,如果不能保证客户端收到的公钥是服务器下发的,那整个通信数据的安全就没法保证。简单总结就是证书被调包。
所以,还得保证客户端收到的证书就是服务器下发的证书,没有被中间人篡改过。

第四层(安全传输证书)

这一层,我们的任务是:保证客户端收到的证书是服务器下发的证书,没有被中间人篡改过。
所以,这里就有两个需求:

  1. 证明证书内容没有被第三方篡改过;
  2. 证明证书是服务器下发的。

其实这些问题,数字证书本身已经提供方案了,数字证书中除了包含加密之后的服务器公钥、权威机构的信息之外,还包含了证书内容的签名(先通过 Hash 函数计算得到证书数字摘要,然后用权威机构私钥加密数字摘要得到数字签名)、签名计算方法以及证书对应的域名。这样一来,客户端收到证书之后:

  • 使用权威机构的公钥解密数字证书,得到证书内容(服务器的公钥)以及证书的数字签名,然后根据证书上描述的计算证书签名的方法计算一下当前证书的签名,与收到的签名作对比,如果一样,表示证书一定是服务器下发的,没有被中间人篡改过。因为中间人虽然有权威机构的公钥,能够解析证书内容并篡改,但是篡改完成之后中间人需要将证书重新加密,但是中间人没有权威机构的私钥,无法加密,强行加密只会导致客户端无法解密,如果中间人强行乱修改证书,就会导致证书内容和证书签名不匹配。所以证书签名就能判断证书是否被篡改;
  • 再考虑证书被掉包的情况:中间人同样可以向权威机构申请一份证书,然后在服务器给客户端下发证书的时候劫持原证书,将自己的假证书下发给客户端,客户端收到之后依然能够使用权威机构的公钥解密证书,并且证书签名也没问题。但是这个时候客户端还需要检查证书中的域名和当前访问的域名是否一致。如果不一致,会发出警告!

从上面的分析可以看到,数字证书中的信息确实能让客户端辨别证书的真伪。

总结

综上所述,相比 HTTP 协议,HTTPS 协议增加了很多握手、加密解密等流程,虽然过程很复杂,但其可以保证数据传输的安全。
HTTPS 访问所面临的问题:

  1. SSL 证书费用很高,以及其在服务器上的部署、更新维护非常繁琐;
  2. HTTPS 降低用户访问速度(多次握手);
  3. 网站改用 HTTPS 以后,由HTTP 跳转到 HTTPS 的方式增加了用户访问耗时(多数网站采用 301、302 跳转);
  4. HTTPS 涉及到的安全算法会消耗 CPU 资源,需要增加大量机器(https 访问过程需要加解密)。
comments powered by Disqus