以前一直认为HTTPS是个很神秘的协议。两年前用Charles抓包时碰到HTTPS,各种配置证书、各种折腾之后,才能看到加密之前的数据。如今登录校园WIFI时,要是一不小心访问了使用HTTPS的网站,那么认证页面就无法打开了。

HTTPS的黑匣子里面到底存在些什么呢?现在是时候揭开HTTPS的神秘面纱了!

1. HTTPS是什么?

以前一直以为HTTPS是一种与HTTP类似的应用层协议,后来才发现HTTPS并不是一种协议。https只是在URI中作为protocol identifier罢了。HTTPS其实是HTTP Over TLSRFC2818 )的简称,也就是运行在TLS协议上的HTTP协议,使用TLS协议对HTTP数据进行加密,从而保证了安全性。

2. TLS协议简介

HTTPS的核心就是TLS协议,那么TLS协议又是什么呢?TLS的全称为Transport Layer Security,也就是在传输层保证安全[RFC5246]。主要分为以下四个协议:

TLS协议中最重要的就是handshake了,在握手阶段通信双方以安全的方式协商好用于之后数据传输的加密方式以及各种密钥。下面将结合wireshark抓包来阐明握手流程。

3. TLS握手流程

Screen Shot 2017-09-03 at 12.39.33

握手的整个流程如上图,*表示的可选项。以访问https://yieldnull.com/为例,下面是用wireshark抓的包(只筛选出TLS)

Screen Shot 2017-09-03 at 12.49.08

3.1 客户端请求建立连接

Screen Shot 2017-09-03 at 12.51.22

客户端首先要向服务器请求建立一个安全连接。需要发送给服务器的必要信息有:

  • TLS 协议版本。
  • Cipher Suites。由于双方对一些加密算法的支持程度可能不同,客户端需要将它支持的加密方法发送给服务器,以供服务器进行选择。
  • Session ID。如果提供的话,表示使用前一个会话中已协商好的密钥,而无需再次协商。
  • Random。客户端生成的随机值,用来生成Master Secret
  • server_name extension。表示访问的是哪个网站。

3.2 服务器确定加密套件

Screen Shot 2017-09-03 at 15.00.43

服务器接收到建立连接的请求之后,要发送以下信息:

  • TLS 协议版本。
  • Cipher Suite。从客户端提供的可选加密方式中选择一个。
  • Session ID。本次会话的ID。
  • Random。随机生成的值,用来生成Master Secret

3.3 服务器发送证书

在发送Server Hello之后,服务器还需要把其证书通过Certificate发给客户端。

Screen Shot 2017-09-03 at 15.05.13

证书的作用在“用数字证书证明你是你”一文中已经阐明。

要是之前确定的加密套件中的秘钥交换算法还需要一些额外的信息,那么服务器还会发送一个Server Key Exchange,用来传递额外的信息。

Screen Shot 2017-09-03 at 15.14.13

3.4 双方完成身份认证

(如果服务器要认证客户端的身份,那么会发送一个Certificate Request来向客户端请求证书,客户端收到请求之后会发送Certificate给服务器)

最后,(确认客户端身份之后)服务器发送Server Done表示我想知道的都已经知道了,该发的也发给你了。

Screen Shot 2017-09-03 at 15.16.01

3.5 生成密钥

通过之前的步骤,通信双方认证了对方的身份,明确了加密套件,现在就缺加密密钥了。

此时,客户端会生成一个premaster secret,并用服务器证书中的公钥进行加密,然后通过Client Key Exchange发送给服务器。

Screen Shot 2017-09-03 at 15.25.41

同时,客户端会在本地使用premaster secret,以及之前在Hello阶段双方生成的两个随机数,生成最终的master secret

服务器收到Client Key Exchange之后,使用其私钥解密出premaster secret。然后使用与客户端相同的方式,生成与客户端相同的master secret

3.6 通知开始加密传输

当双方都得到master secret之后,就会发送Change Cipher Spec通知对方:我开始用之前商量好的加密方式以及密钥传输数据了。

Screen Shot 2017-09-03 at 15.37.15

3.7 确保密钥可用

为了确保之前的协商的确是成功了,双方还需要确认一下双方使用的密钥是不是一致的。怎么确认呢?那就把从Client Hello以来握手过程中双方通信的所有信息加密之后,再给对方发送一遍。要是对方发过来的信息解密之后与自己记录的相同,则表示密钥生效了!

Screen Shot 2017-09-03 at 15.56.44

4. 加密套件与密钥

上一节仅介绍了握手的流程,现在来仔细看看其中涉及到的加密套件(Cipher_suite)与master secret

4.1 加密套件

加密套件定义的是在整个数据传输过程中使用到的加密方式。以TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256为例,其包含以下算法

  • 密钥交换算法。用来交换密钥。例如ECDHE_RSA
  • 对称加密算法。用来加密信息。例如AES_128_GCM
  • 信息摘要算法。用来计算摘要,防止篡改。例如SHA256
  • 伪随机函数。生成master secret。要用到信息摘要算法。

4.2 master secret

上一节提到,客户端与服务器会根据premaster secret以及二者在Hello阶段各自生成的随机数,产生相同的master secret。二者使用的函数为

Screen Shot 2017-09-03 at 16.11.53

至于生成的master secret,其格式为

client write MAC key server write MAC key client write encryption key server write encryption key client write IV server write IV

前两个是计算摘要用的KEY,中间两个是加密时用的,最后两个适用于加密套件使用AEAD时。

4.3 两个随机数

为什么在Hello阶段,客户端与服务器会各自用明文传递一个随机数呢?

有一种说法是为了增加master secret的随机性,要是没有这两者,仅仅使用客户端生成的premaster secret是无法保证随机性的,进而可能会导致密钥被猜出来。

5. 总结

HTTPS的原理很简单,就是把原本用明文传输的数据加密之后再传输。困难的地方在于如何安全地协商加密方式,相当于把明文传输数据的风险转移到了传输密钥上。

传输密钥必定不能使用明文,因此需要引入非对称加密,比如RSA,用RSA加密密钥。但是RSA算法需要传递公钥,公钥只能明文传输,因而容易被中间人攻击(篡改)。所以引入了第三方权威机构来认证公钥,使用数字证书来认证公钥的合法性。

当然,仅仅有数字证书还是不够的,因为中间人同样可以在证书传输过程中篡改证书。故而引入了数字签名,用CA的私钥给证书签名。私钥只有CA持有,而CA的公钥往往内置于操作系统或浏览器,可以值得信任。因此可以用CA的公钥解密签名,从而可以判断证书是否被篡改。

通过证书以及签名判断通信双方的身份之后,就能用公钥加密信道,交换用于对称加密的密钥。生成密钥时要保证随机性,防止密钥被猜出。

得到密钥之后,就可以愉快地加密数据并安全传输了。当然,收到数据之后还是得算一下摘要,验证一下是否被篡改,万一被人猜出了加密密钥呢。摘要算法也是有密钥的,两者不会同时被猜出来吧?

(完)

References: