TOC

了解 HTTPS 背后的原理

之前生成证书那篇文章中总结了很多 X.509 的知识点,这次再通过 HTTPS 来看看 PKI 机制的一个完整应用。

加密算法方面的验证,或者公式什么的,太过复杂、繁琐,我看不懂,也不想弄懂,我只关心整套流程是怎么在发挥作用。

为什么使用 HTTPS

安全,安全,安全

HTTP 协议的天生缺陷:

  1. 窃听 -> 需要对通信内容进行加密
  2. 篡改 -> 需要对通信内容进行校验
  3. 冒充 -> 需要一个可信赖的身份认证体系
    有了 HTTPS 之后,再冒充只能搞相近的域名做钓鱼了。

答案就是 TLS(HTTP + TLS = HTTPS)。

TLS

Version PublishTime Status
SSL 1.0 - unpublished
SSL 2.0 1995 RFC6176 (Deprecated in 2011)
SSL 3.0 1996 RFC7568 (Deprecated in 2015)
TLS 1.0 1999 RFC2246
TLS 1.1 2006 RFC4346
TLS 1.2 2008 RFC5246
TLS 1.3 2018 RFC8446

SSL 协议由网景公司开发,后来被 IETF 标准化,正式名称叫做 TLS,目前应用最广泛的应该还是 TLS 1.2。
注释:SSL/TLS 可以认为是同一个协议,不过版本不相同。

SSH 本来是一个非常成功的网络通信协议,也被应用来给一些应用层协议提供安全、透明的网络通道,但是其传输层和应用层过于耦合,必须要有 SSH 服务器支持才行。
因此借鉴 SSH 的网络传输层设计思路,TLS 被开发出来,用来封装 TCP/UDP 包,不会影响应用层数据,所以被广泛地与各种应用层协议结合使用,HTTPS、SMTP 中的 STARTTLS 就是其中的代表。

之前说的 PKI 机制可以解决证书可行的问题。
非对称加密计算量太大,就只用非对称加密来协商会话密钥,然后使用会话密钥来做对称加密。

公钥加密

数字证书

非对称加密

  1. 对称加密使用同一个密钥,有很多种优秀的加密算法可以保证只要密钥不泄露,几乎无法解密。
  2. 非对称加密相当于使用两个不同的密钥:公钥、私钥。
    1. 根据公钥几乎无法计算出私钥。
    2. 一般使用公钥加密,私钥解密。
  3. 非对称加密设计非常复杂的数据计算,所以加密解密成本非常高。相比较而言,对称加密的加密解密成本几乎可以忽略。

PKI 与证书链

可以看看前面发的 生成证书那篇文章

虽然由于政治、

HTTPS 全过程

这里只看加密通信的部分,SYN、ACK 就跳过了。

方法

  1. 打开 WireShark,应用 tls 过滤
  2. curl https://www.markjour.com/
  3. 找到 IP 之后,修改过滤规则为 ip.addr == 121.42.82.115 and not tcp.len == 0
  4. 停止网络监听,对那一串网络包逐条查看

总结

主要思想是利用非对称加密实现一个安全的数据交换通道,两端生成相同的密钥,用于对称加密。

重点就是前面这一段应用非对称加密算法的握手协议,也就是一个密钥交换过程,这一阶段巧妙地在明文通信基础上保证了通讯安全。
PS:由于这个阶段还是明文通信,如果直接交换对称加密密钥,就相当于没有加密,只能非对称 + 信任链来解决这个问题。

  1. 客户端发起 TLS 握手 Handshake Protocol: Client Hello
    版本信息,支持的加密套件列表 cipher suite,支持的压缩算法列表 compression method,支持的 TLS 拓展 extensions,随机数 randomC 等。
  2. 服务器响应 TLS 握手
    • Handshake Protocol: Server Hello
      服务器端会从客户端支持的那些个列表中各选一种。
      也会返回一个随机数 randomS
    • Handshake Protocol: Certificate
      证书链,用于向客户端验明正身,以及后面的密钥交换
    • Handshake Protocol: Server Key Exchange
    • Handshake Protocol: Server Hello Done
  3. 客户端校验证书并实现证书协商
    • Handshake Protocol: Client Key Exchange
      生成一个随机数 PremasterSecret,使用服务器公钥加密,发给服务器
      重点:三个随机数,生成一个会话密钥
      randomC + randomS + PremasterSecret -> SessionKey
    • Change Cipher Spec Protocol: Change Cipher Spec
      通知服务器协商完成,以后就使用 SessionKey 通信
    • Handshake Protocol: Encrypted Handshake Message
      将之前通信使用的数据,使用协商好的密钥和算法加密,发送给服务器,核对通信是否正常
  4. 服务器确认
    • Change Cipher Spec Protocol: Change Cipher Spec
      服务器使用私钥解密拿到客户端发送过来的 PremasterSecret,然后使用相同的方法生成 SessionKey
      使用 SessionKey 解密客户端发送过来的加密信息,检查是否正确无误
    • Handshake Protocol: Encrypted Handshake Message
      服务器同样也加密一段数据给客户端
  5. 客户端校验数据没有问题之后,就开始和服务器进行应用层通信

双向认证

即服务器需要验证客户端身份

  1. 客户端 Hello 之后,服务器需要在 Hello Done 之前发一个 Certificate Request
  2. 客户端校验服务器证书之后,应该向服务器端发出自己的证书
  3. 服务器对客户端证书进行校验

<未整理完成>

加密套件

  1. 认证算法
  2. 密钥交换算法
  3. 对称加密算法
  4. 哈希算法(或者说信息摘要算法)

验证证书

  1. 计算是否正确
  2. 证书是否吊销
  3. 是否在有效期
  4. 域名是否匹配

TLS 拓展

SNI

这个拓展非常关键,为什么呢?

对于 Web 服务来说,80 端口可能绑定了 3 个域名,他们是不同的网站,承载着不同的业务,他们的证书很可能不相同,
但是客户端 Hello 过来的时候没有指定域名,服务器不知道应该按照那个网站的证书来处理。

RFC4366 为 TLS 添加了一批拓展,包括一个叫做 Server Name Indication,简称 SNI,的拓展,解决了这个问题。

下面是 WireShark 的抓包数据,关于 SNI 这一部分:

0000   00 00 00 15 00 13 00 00 10 77 77 77 2e 6d 61 72   .........www.mar
0010   6b 6a 6f 75 72 2e 63 6f 6d                        kjour.com

Type:                    00 00      server_name
Length:                  00 15      21
Server Name list length: 00 13      19
Server Name Type:        00
Server Name length:      00 10      16
Server Name:             77 77 77 2e 6d 61 72 6b 6a 6f 75 72 2e 63 6f 6d
                                    www.markjour.com

据说 IE6、IE7 不支持 SNI,影响就是:如果服务器上绑定了多个域名,浏览器就可能得不到响应(TLS 连接都失败了)。

参考资料与拓展阅读