浏览器建立SSL/TLS协议连接,实际上就是使用多个子加密协议组合,最终选择合适的加密算法进行数据安全传输,这种算法组合本身被叫做 “密码套件”

TLS 密码套件命名

TLS 的密码套件命名看起来很长,但是实际上非常规范,格式很固定。基本的形式是

密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法

比如 ECDHE-RSA-AES256-GCM-SHA384

所表示的含义为:

握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度256位,分组模式是 GCM ,摘要算法 SHA384 用于消息认证和产生随机数

对称加密

比较流行的算法包括: DESTtriple-DES(3DES)RC2RC4ChaCh20AES ,其中 RC4RC2DES3DES 都已经被证明不安全,不应该再使用

  • ChaCh20 :Google 开发的一种加密算法,其安全性和性能都很好,但是由于其不是公认的标准算法,所以目前还没有被广泛使用

  • AES :目前最流行的对称加密算法,目前是 TLS 的标准算法,其密钥长度可以是 128 位、192 位、 256 位或者更长

非对称加密

在TLS里面,非对称加密算法主要用于密钥交换和身份认证,比较流行的算法包括: RSADSAECCDH

其中 RSADSADH 都是基于数论的算法

ECC 是基于椭圆曲线的算法,ECC目前比较常用的两个曲线是 P-256(secp256r1,在 OpenSSL 称为 prime256v1)和 x25519

摘要算法

数字签名通常是使用单向加密的摘要算法,摘要算法主要负责计算内容的 哈希值(HMAC),这个哈希码是唯一的,并且无法反向推导。

密钥交换算法

密钥交换算法主要用于在握手阶段,客户端和服务器之间交换对称加密算法的密钥,常见的密钥交换算法包括 RSAECDHE

现代互联网都是使用 ECDHE 进行密钥交换算法

TLS 1.2

TLS 1.2 协议组成

TLS 1.2 主要有四个子协议:

  • 记录协议(Record Protocol)
  • 握手协议(Handshake Protocol)
  • 警告协议(Alert Protocol)
  • 变更密码规范协议(Change Cipher Spec Protocol)

记录协议

记录协议规定TLS传输的基本单位:记录(record)

record 可能包含长度,描述和内容,具备分块、压缩、编码、解压缩、重组等等和TCP分块类似功能,类似于TCP的Segament

此外,这个协议还规定了安全通信的能力:

  • 可靠连接 :使用 MAC(Message Authentication Code,消息验证码)为数据提供完整性校验,TLS 目前使用的 HMAC 也属于 MAC 的一种。在握手阶段可以选择性地使用该功能
  • 私有连接 :比如对称加密使用的 AESCHACHA20 (需要注意记录协议也可以提供不加密的封装,比如在握手阶段的 Hello 报文,意味着整个连接都是可定制化的,参数可选)

警报协议

警报协议用于在通信过程中发生错误时,向对方发送警报信息,比如握手失败、证书无效、加密失败等等,类似于HTTP的状态码

如:

  • bad_record_mac :错误的MAC地址
  • decode_error :解码异常
  • protocol_version :表示旧版本不受支持

握手协议

握手协议是TLS的核心协议,用于在客户端和服务器之间进行身份认证、密钥交换、协商加密算法等等

握手协议的主要内容分为以下三点:

  • 身份认证 :利用CA端进行身份认证,身份认证的过程会用到非对称加密算法,注意HTTPS支持客户端和服务端双向认证,默认是服务单单向认证,客户端认证是可选的
  • 安全参数协商 : 保证被认证数据的机密性,需要用到比如哈希算法、密钥、加密算法等算法,对于数据加密处理
  • 可靠协商 :可靠协商指的是防止数据传输过程中被篡改

握手协议定义了这些命令: ClientHelloSeverHelloCertificateServerKeyExchangeCertificateRequestServerHelloDoneClientKeyExchangeCertificateVerifyChangeCipherSpecFinished

变更密码规范协议(Change Cipher Spec Protocol)

变更密码规范协议用于在握手过程中,通知对方之后的数据都将使用新的加密算法进行加密,这个协议只有一个命令: ChangeCipherSpec

Application Data 协议

Application Data 协议 用在通信阶段,封装了应用层的数据,通过 Record 协议 封装之后,再通过 TCP 协议 转发出去

此协议用于握手连接完成之后的数据传输规范,实际上可以看作是TLS和TCP的协议的对接

TLS 1.2 握手流程

HTTPS连接定义:

HTTPS交互流程图如下所示:

第一次握手

  1. 客户端发送一个 ClientHello 请求,同时传递一些必要参数:
  • client_version :客户端支持的TLS版本
  • client_random :客户端生成的随机数,是后续对称加密密钥的必要参数之一
  • session_id :会话ID,如果客户端想要重用HTTPS会话,则在连接的时候需要携带此参数,否则为空
  • cipher_suites :客户端支持的加密套件
  • compression_methods :客户端支持的压缩会话列表
  • extensions :方便以后扩展新字段,该字段也是TLS 1.3的核心部分
  1. 服务器收到 ClientHello 请求之后,返回一个 ServerHello 响应,同时传递一些参数:
  • server_version :服务器选择合适的TLS版本
  • server_random :服务器生成的随机数,是后续对称加密密钥的关键参数
  • cipher_suite :从 cipher_suites 选择合适的加密套件
  • compression_method :选择合适的压缩算法
  • extensions :扩展内容

第二次握手

  1. 第二次握手是从服务端开始的,服务端发送完 ClientHello 后,接着发送 Certificate ,包括服务端的证书链,证书链中包含了服务端的公钥,客户端收到证书之后,会对证书进行校验

  2. 数字证书传递之后,接下来是关键的一步,也就是密钥交换算法的协商( Server Key Exchange ),密钥交换的算法实际上是对于会话密钥(对称加密方法)选择,也就是如何安全的把实际交互的对称密钥告知服务器,目前HTTPS采用ECDHE算法

  3. *如果本次HTTPS是双向认证,则可以通过 CertificateRequest 索要客户端证书,保证双向安全

  4. 服务端发送 ServerHelloDone 告知客户端,服务端的握手阶段已经完成,等待客户端的响应

第三次握手

  1. *如果服务端要求客户端提供证书,那么客户端会发送 Certificate ,证书中包含了客户端的公钥,服务端收到证书之后,会对证书进行校验

  2. 在单向认证中,客户端生成客户端公钥,用非对称加密的公钥进行加密,然后发送 ClientKeyExchange 给服务端,到此,客户段两个“半片钥匙”都已经拿到

  3. *如果有客户端证书校验,则需要加一步 CertificateVerify 操作

  4. 做完ECDHE传输之后,客户端和服务端各自持有 Client ParamsServer Params 两个公钥,于是开始计算真实的会话密钥

    1. 双方用 Client ParamsServer Params 两个公钥加复杂算法,计算出一个随机数 Pre-Master Key
    2. 双方用 Pre-Master KeyClient RandomServer Random 三个随机数,做伪随机数函数计算,生成最终的会话密钥 Master Key ,此外为保证安全性,还要再次加上摘要算法
  5. 会话密钥生成后,客户端就可以发送 Change Cipher Spec 告知服务端

  6. 客户端再发送一个 Finished 消息( Encrypted Handshake Message ,所有数据摘要)把之前所有的消息做个摘要,用会话密钥加密,发送给服务端做个验证

第四次握手

服务端收到客户端的回应后,也会发送 Change Cipher SpecFinished 消息,让客户端确认

两边核实无误,握手完成,开始正式的数据传输

TLS 1.3

TLS 1.3 中,废弃了 Session Ticket 机制和 Session ID 机制,改变了密钥派生的机制,废弃一大堆不安全的算法,并且握手信息也被部分的进行了加密。对于握手流程来说,由之前的2-RTT变成了1-RTT,大大提高了握手的速度

TLS 1.3 握手流程

握手协议主要分为三个流程:

  1. 密钥交换 :选择TLS协议版本和加密的算法,并且协商算法所需的参数。这段是明文传输的
  2. 服务器参数 :建立其他握手协议参数,例如是否需要认证客户端,支持何种应用层协议等
  3. 认证 :对服务器进行认证(包括可选的客户端认证)并且提供密钥确认和验证握手完整性功能