meishaoming / blog

MIT License
1 stars 2 forks source link

CA 与 HTTPS #102

Open meishaoming opened 4 years ago

meishaoming commented 4 years ago

一、首先来看我们要解决什么问题?

当我们用浏览器访问一个网页的时候,由于 HTTP 访问的数据是明文的,如果有人在中间修改了网页,我们也发现不了。

有哪些途径可以在「中间」修改网页?

比如,一般我们都是通过路由器上网,如果在路由器要解析到回传给你的是一个 HTML ,那就可以在 HTML 中插入一些数据再返回给你。

我们访问目标网站中间不仅仅经过自己家里的路由器,还经过运营商的很多节点路由才最终能跟服务器交互,那么这中间任何一环都有可能篡改我们的数据。

要解决这个问题,就需要对客户端、服务器两者之间交互的数据进行加密。也就是说,传输的数据只有客户端和服务器看得懂,其它人看不懂。数据一旦被更改就会被发现。

分解一下这里的需求:

  1. 能验证数据完整性。也就是说数据被加了一点、删了一点都能检查出来
  2. 确认数据的来源,数据必须是我们期望的人生成的。我访问哪个网站,就期望这个数据必须由这个网站直接生成的
  3. 数据加密。别人就算拿到了数据,也理解不了数据的内容

二、如何实现数据完整性?

发送数据之前先取数据的「摘要」,收到数据的时候以同样的算法也算一遍「摘要」。对比两份摘要就知道数据有没有被篡改。

但仅仅有「摘要」还是不够的。如果有人改完数据、重新算了一份「摘要」呢?所以我们不仅要能识别数据完整,而且还要有能力验证这份数据是不是「我们认为的对方」生成的。

三、如何确认数据来源?

把生成的「摘要」用私钥加密。私钥是非对称加密里的概念,非对称加密的特点是私钥加密只能由公钥解密,公钥加密只能由私钥解密,公钥和私钥是完全不同的。

这样的话,服务端生成一对密钥:私钥+公钥。私钥保存起来,公钥就放到公网上大家都可以拿到。

如果用服务端的公钥成功解密了一串数据,那这串数据肯定是由这个服务器生成的。

对数据生成一个「摘要」,然后服务端用私钥加密这个「摘要」,最后得到的就是对这串数据的「签名」。有了「签名」,就可以验证数据的来源。

四、从哪里获取公钥?

我收到了来自服务端的数据,想要服务端用的公钥解密「签名」。问题来了:

如果有个人生成了一对公钥+私钥,把公钥给我并且欺骗我这就是服务端的公钥,然后用它的私钥加 密数据发给我。那我岂不是认为这个数据是来自服务端的?

所以问题是:我从哪里去拿到服务端的公钥?我怎么知道我拿到的就是这个服务端的公钥?

现实生活中是这样解决的:

  1. 有威权的组织,我们叫做证书中心。它们有公钥+私钥,不同的是它们的公钥是公开的,被广泛承认。比如浏览器里就内置了这些公共组织的公钥,也可以手动添加我们信任的公钥
  2. 把服务端的公钥和域名信息用证书中心的私钥加密起来,生成的就叫作「证书」。这个「证书」就留在服务器上,以备随时发给 client
  3. client 会先拿到服务端的「证书」,并到证书中心去验证(就是用证书上中心的公钥去解密),以验证服务器的是不是被谁的那个服务器

注意,不是谁都能随随便便用证书中心的私钥去加密自己的公钥,这需要经过一系列申请和付费才行。(letsencrypt 是免费的,但三个月要刷新一下)。

五、HTTPS

我们要对 HTTP 加密。不仅要确认数据完整性、确认数据来源,还需要对数据本身加密,要让别人看不懂数据的内容。比如我们可能在通过 HTTP 向服务器提交账户、密码等关系信息,明文的肯定不行。

要想对数据本身加密,在客户端和服务器之间就必须先协商好一个密钥,我们叫作 key。这个密钥是对称加密的密钥。如何协商呢?

这就相当于 A 和 B 对话,需要经过 C 来传达,那么 A 和 B 如何协商一个 key 让 C 都不知道呢?

TCP 连接建立之后,HTTPS 的交互过程:

  1. client 向 server 发送 client hello,其中包括:client 的 SSL 版本、支持的加密算法列表
  2. server 返回 sever hello, 其中包括:server 的 SSL 版本,选择的加密算法、server 的证书
  3. client 收到证书后会校验它:证书有没有过期、是否是信任的CA签发的、CA公钥能否解出证书里的签名(sever公钥+server域名信息)、证书里的域名跟访问的域名是否一致
  4. client 生成一个 pre-master secret(或随机数),用 server 的公钥加密,发给 server
  5. client 和 server 用这个 pre-master secret 经过加同的一系列步骤生成对称密钥 key
  6. client 和 sever 分别切换到 key 加密传输数据。ssl 交互结束。

C 能不能知道这个 key ?

不能。因为 client 生成的 pre-master secret 用服务端的公钥加密,只能被服务器的私钥解密。

参考:

hutao-fmtech commented 3 years ago

非常清新明了