跳到主要内容

1 篇博文 含有标签「HTTPS」

查看所有标签

· 阅读需 14 分钟
熊滔

如果你使用 HTTP 访问网站或者进行通信,你的一切都毫无秘密 ,因为你的所有信息都是明文传输的,并且你收到的信息都可能是伪造的,想象你访问一个需要输入私密信息的网站,但是网站的内容已经被别人偷偷的篡改过了,你提交的信息都提交到别人的服务器上了,信息由此泄露。

由于 HTTP 是明文传输的,所有的内容没有经过任何的加密,截获到你传输流量的人,都可以从其中获取传递的信息,对付这种窃听,我们只需要对消息进行加密即可。

加密和解密都需要用到密钥,根据加密和解密使用的密钥是否相同,加密分为两种:

  • 对称加密:加解密使用同一个密钥

  • 非对称加密:加密和解密使用的不同的密钥

非对称加密会生成两个密钥,使用其中一个加密,另外一个可以解密,且必须使用另外一个才能解密。这两个密钥其中一个是公开的,称之为公钥,另一个是绝不能在互联网上传播的,称之为私钥。

假设我们对消息使用对称加密的方式进行加密,窃听者没有密钥,就无法解密了,但是你有没有想过一个问题,密钥要怎么传递,如果是明文传递,那么密钥也可以被窃听到,那么加密这件事就毫无意义。你可能会说,我们对密钥也进行加密,那么加密密钥的密钥如何传递,又回到了原点。

这个时候非对称加密要出场了,通信双方首先在本地生成公钥和私钥,然后互相把公钥发送给对方,让对方使用接收到的公钥加密消息,即使有窃听者,也只能获取到公钥,由于没有私钥,也无法解密消息。

sequenceDiagram
actor A
actor B
A->>A: 本地生成公钥 A 和 私钥 A
B->>B: 本地生成公钥 B 和 私钥 B
A->>B: 公钥 A
B->>A: 公钥 B
A->>A: 使用公钥 B 对 message1 加密 → Emessage1
A->>B: Emessage1
B->>B: 使用私钥 B 对 Emessage1 解密 → message1
B->>B: 使用公钥 A 对 message2 加密 → Emessage2
B->>A: Emessage2
A->>A: 使用私钥 A 对 Emessage2 解密 → message2

非对称加密相对于对称加密的成本要高很多,要进行很复杂的运算,如果通信过程一直使用非对称加密,会使得通信时间变长,于是就有了混合加密,即通过非对称加密传递对称加密的密钥,然后使用对称加密的方式进行通信,因为对称加密的密钥是加密过的,因此窃听者无法得知,这种方式使成本和保密性都得到了保证。

sequenceDiagram
actor A
actor B
B->>A: 公钥
A->>A: 生成对称加密的密钥 key,并使用公钥加密 → EKey
A->>B: Ekey
B->>B: 使用私钥解密 → key

但是非对称加密只是解决加密的问题,但无法确定对方的身份,即你怎么确认公钥一定是 B 发给你的呢?假设存在这么一个人,它劫持双方通信的流量,并且假冒是通信的对方,例如对于 A,它假冒是 B 与其交换密钥进行通信,对于 B,它假冒是 A 与其通信,所有的消息经过它进行了一次转发。

sequenceDiagram
actor A
actor C
actor B
A-->C: key-AC
C-->B: key-CB
A->>C: key-AC + message1 → EMessage1
C->>C: key-AC + EMessage1 → message1
C->>B: key-CB + message1 → Emessage2
B->>B: key-CB + Emessage2 → message1

A 试图与 B 通信,但是被 C 劫持了,C 假冒 B 与 A 交换了密钥,同时假冒 A 与 B 交换了密钥,这样 A 与 B 之间的所有消息都会被 C 看到,这种攻击方式称为中间人攻击,很形象。

之所以中间人有机可乘,是因为通信双方无法验证对方的身份,那如何证明身份呢,这就需要用到数字证书。数字证书需要向专门的机构(Certificate Authorities 机构,简称 CA)申请,我们需要提交我们的公钥、域名等信息给 CA 机构,并且还需要证明你的确是这个域名的持有者,CA 机构验证完成之后,会生成一个数字证书。

这时如果 A 向 B 请求信息,B 不应该直接返回它的公钥,而是返回申请的证书,浏览器会验证证书的合法性:

  1. 证书是否是由可信任的 CA 机构颁发的

  2. 证书中的域名信息和当前请求的域名相吻合

但是有一种可能,证书可能会被篡改,比如把证书里面的公钥替换为自己的,有什么办法可以知道消息被篡改了呢,那就是数字签名。CA 机构在颁发数字证书,还会生成一个数字签名,当浏览器收到证书后会计算证书的签名与下发的签名是否相同,如果相同则表示没有被修改,值得信任。那这个时候你就会问,数字签名不可以被篡改吗,还真的不能,只能由 CA 机构生成,其它生成的都无效,这又是为什么,这就要看数字签名是如何生成的:

  1. CA 机构会生成一个公钥和私钥

  2. CA 机构会使用私钥对数字证书进行加密,得到的就是签名

  3. 浏览器使用 CA 机构的公钥进行解密,与签名进行比较,如果一样说明没被篡改

因为签名是使用 CA 机构的私钥加密的,而私钥只有 CA 机构有,别人无法生成签名,即使随便生成了一个,浏览器计算得到的签名肯定和这个签名对不上,就知道被篡改了。

事实上,使用私钥对全部的消息进行加密比较耗费时间,一般是根据消息生成哈希值(相同的内容可以生成相同的哈希值,对内容篡改后,哈希值会大不相同),然后对哈希值加密得到数字签名。

只有这三个条件都符合,我们才认可对方的身份,而不是第三方进行了伪造,然后就会提取证书中的域名提供的公钥。

那么中间人有没有可能伪造数字证书:

  1. 申请一个别的域名的证书,替换为自己的

    浏览器会验证证书里面的域名与请求的域名是否吻合,域名信息不对,会被认为是不安全的

  2. 也向机构申请一个证书,并且声明自己是这个域名的持有者

    无法证明是域名的持有者,CA 会给一个记录让你配置在域名相关信息中,因为你不是域名的所有制,自然无法配置,所以不会颁发证书

  3. 篡改证书信息

    证书使用 CA 机构的私钥进行了签名,篡改了信息就无法使签名与篡改后的签名一致

    把签名也篡改了?没有 CA 机构的私钥,无法篡改

所以 HTTPS 的总体通信如下

sequenceDiagram
actor 浏览器
actor 服务器
浏览器->>服务器: Hello
服务器->>浏览器: 证书
浏览器->>浏览器: 验证证书合法性,提取服务器的公钥 pubKey
浏览器->>浏览器: 生成对称加密的密钥 key,使用公钥加密 pubKey + key → Ekey
浏览器->>服务器: Ekey
服务器->>服务器: 使用私钥解密 priKey + Ekey → key
Note over 浏览器,服务器: 愉快的使用 key 进行加密通信

最后还有一个值得注意的问题,浏览器是如何获得 CA 机构的公钥的,你无法保证 CA 机构的公钥不是伪造的,其实 CA 机构的公钥也是以证书的形式交付给浏览器的,那么问题来了,这个证书是谁生成的,其实 CA 机构也是有层级的,这个证书是由上一级的 CA 机构颁发,处于最上级的 CA 机构称为根 CA 机构,它们的证书是谁颁发的呢,是它们自己,自己给自己颁发证书,这种证书称为自签名的证书。

如果你收到了一个自签名的证书,但不是根 CA 机构的,那么你就要注意了,如果信任该证书,且该机构包含恶意,你的信息可能被其监听到,甚至被修改,所以对于不信任的证书不要添加到信任列表中。

  1. 有了 HTTPS,使用公共场所的 WiFi 还安全吗

    如果你使用的 HTTPS 那就没问题,虽然能看到你发送的所有字节,但是不知道你们交流了什么。但是如果你使用了 HTTP,你的内容可以被看到,甚至返回的内容都会被修改,使得你提交的内容会指向一个不安全的网站

  2. 公司能监控到你的 HTTPS 内容吗

    在每个信任链的根部都有一个隐含的受信任的 CA,这些权威机构的列表存储在你的浏览器中。你的公司可以利用他们对你的机器的访问,将他们自己的自签名证书添加到这个 CA 列表中。然后,他们可以拦截你所有的 HTTPS 请求,对于一些网站的证书,由他们的假 CA 签署。由于你使用的是公司提供的证书中的公钥对你的所有 HTTPS 请求进行加密,他们可以使用相应的私钥来解密和检查(甚至修改)你的请求,然后将其发送到预定地点。他们可能不会这样做,但他们可以。

  3. 棱镜门事件

    法官要求公司交出它们的私钥,有了私钥,就可以解密出加密使用的密钥,所有的消息都会被看到。

参考资料: