Https 简单入门

http协议传输的数据都是在网络上明文裸奔的,这样很容易会被网络的中间节点窃听篡改冒充

http向https的演变过程,可以模拟成下面几步。

1. 对称加密

1
2
3
4
5
  Client  --------  Server
① 对称加密
| ------> | 解密
② 对称加密
解密 | <------ |

客户端和服务端使用对称解密算法例如AES,传输前对数据加密,然后由对方解密的方式。但这种方式在对外的web服务场景下行不通,因为需要对外暴露对称算法的钥匙。

2. 非对称加密

1
2
3
4
5
      Client  ---- 🐶 ----  Server
① 公钥加密
| ------> | 私钥解密
② 私钥加密
公钥解密 | <------ |

采用非对称加密算法只需要对外暴露同一把公钥。 这样客户端使用公钥加密,中间人(那只🐶)无法窃听数据,服务端私钥解密。然后服务端使用私钥加密,中间人无法冒充,客户端再通过公钥解密。

这个过程解决了一些问题,但还是有很多安全风险

  • 传输第①步,公钥加密的数据虽然不能被中间人窃听,但是中间人可以自己采用公开的公钥来重新生成数据,达到篡改的目的。
  • 传输第②步,私钥加密的数据虽然不能被中间人冒充,但是中间人可以使用公钥来窃听数据。

除此之外,非对称加密的比对称加密更加消耗cpu资源
总结来说,采用非对称加密,解决了中间人冒充的问题,但不能解决数据篡改和数据窃听的问题。

3. 终极解决方案:对称加密和非对称加密联合

1
2
3
4
5
6
7
8
9
              Client  ------- 🐶 --------  Server
① 公钥加密[对称密匙]
| --------------> | 私钥解密获取对称密匙
② 私钥加密一段校验数据
公钥和对称密匙确认 | <-------------- |
③ 对称加密
| --------------> | 对称解密
④ 对称加密
对称解密 | <-------------- |

再用文字描述下这个过程

  • ①:客户端使用公钥加密对称加密要使用的密匙和某随机字符串,中间人无法窃听这个密匙,服务端使用私钥解密,获取对称密匙和随机字符串
  • ②:服务器生成一段校验数据,例如先用对称密匙加密随机字符串,再用私钥对结果加密。中间人虽然可以用公钥解密这段数据,但是解密出来的结果中间人完全不知道是什么玩意儿。客户端依次使用公钥和对称密匙解密,核对下随机字符串,确认服务端可信。
  • ③④:接下来客户端和服务端就可以安全的使用对称加密来传输数据了。

这个过程初看起来已经无懈可击了,中间人已经一点办法都没有了。但其实还隐藏了一个重要问题—客户端如何获取公钥并相信这个公钥呢?举个例子,你的https网站发布了,如果客户端拿到了一个虚假的公钥,中间人使用对应的虚假私钥冒充服务器,你的网站就轻而易举被劫持为钓鱼网站了。

4. Https全过程

解决服务端给出公钥的可信任问题很难,可以在浏览器内置世界上所有安全的公钥,但量又太大;有某个机构提供一个实时校验网站公钥的服务,这个服务本身又不一定安全和高效。

现实世界中,解决信任问题的方法往往是有“权威机构”或者权威人物背书,其实https的方法也差不多。
https的网站会提前向一些权威机构申请数字证书,https数据传输前,服务端把数字证书发送给客户端,操作系统里内置这些可信任的权威机构的数字证书,权威机构校验通过了,服务器发送的数字证书以及里面包含的公钥就是可信任的。

所以https的完整过程,还需要在上面的过程里加入服务器返回数字证书的过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
              Client  ------- 🐶 --------  Server
① 客户端hello
| --------------> |
② 服务端返回数字证书
客户端校验数字证书 | <-------------- |
③ 公钥加密[对称密匙]
| --------------> | 私钥解密获取对称密匙
④ 私钥加密一段校验数据
公钥和对称密匙确认 | <-------------- |
⑤ 对称加密
| --------------> | 对称解密
⑥ 对称加密
对称解密 | <-------------- |

以上所说的“权威机构”代指的是“数字证书认证机构”(Certificate Authority,缩写为CA),它们的数字证书作为系统根证书内置在操作系统里面,macOS系统可以通过[钥匙串->系统根证书]查看。

其实客户端通过CA根证书验证服务端数字证书的有效性,也是一次非对称解密的过程。以下简单描述下这个过程。

服务器发送的证书里(chrome浏览器点击地址栏最左边,能看到证书的详细内容),主要包含了以下几个内容:

  • 证书发布机构,即哪家CA
  • 证书的有效期
  • 证书的所有者,以及相关的证书的域名、公司名等等
  • 公钥
  • 证书签名

客户端校验证书的可信性,可以简单分为下面几步

  1. 校验证书声明的CA在操作系统的根证书里面
  2. 校验证书在有效期内
  3. 校验证书的签名,这一步能够证明此证书确实是由CA机构颁发的。

其中校验证书签名是关键,证书签名是网站申请证书时,CA机构对一个hash值使用CA私钥对称加密后的字符串。
可以用表达式表达为:

1
sign = encrypt(hash("证书机构" + "证书有效期" + "证书所有者" + "公钥"))

校验签名的步骤:

  1. 客户端从系统根证书中取出对应CA的公钥,然后对签名解密获取到hash值。
  2. 客户端使用相同的方式拼接证书信息,使用相同算法得到hash值。
  3. 比较解密出来的hash值和客户端拼接的hash值是否相同,相同则通过。

这个过程其实完成了这么一件事情,客户端看了一眼证书提供的信息,然后通过CA公钥解密,证明了证书提供的信息是被拥有CA私钥的机构确认过的(证书的签名),便相信了证书提供的信息。

就像现实生活中的票据,相信票据中的信息,因为有一个独一无二的机构签章(虽然可以伪造,但是非对称机密的签章是不可伪造的)

最后

以上描述了http向https演进时可能发生的一些过程,非对称加密真是一个伟大的发明,解决了信息世界的信任问题。
但上面内容也还有很多不够严谨不够完整的表达,比如CA的证书其实是一个层级结构,证书可能不是CA的根证书签署的,而是CA信任的某个机构签署的,但这些都不影响https利用对称加密和非对称机密去实现安全性的本质过程。