浏览器建立SSL/TLS协议连接,实际上就是使用多个子加密协议组合,最终选择合适的加密算法进行数据安全传输,这种算法组合本身被叫做 “密码套件”
TLS 密码套件命名
TLS 的密码套件命名看起来很长,但是实际上非常规范,格式很固定。基本的形式是
密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法
比如 ECDHE-RSA-AES256-GCM-SHA384
所表示的含义为:
握手时使用 ECDHE
算法进行密钥交换,用 RSA
签名和身份认证,握手后的通信使用 AES
对称算法,密钥长度256位,分组模式是 GCM
,摘要算法 SHA384
用于消息认证和产生随机数
对称加密
比较流行的算法包括: DES
、 Ttriple-DES(3DES)
、 RC2
和 RC4
、 ChaCh20
、 AES
,其中 RC4
、 RC2
、 DES
、 3DES
都已经被证明不安全,不应该再使用
ChaCh20
:Google 开发的一种加密算法,其安全性和性能都很好,但是由于其不是公认的标准算法,所以目前还没有被广泛使用AES
:目前最流行的对称加密算法,目前是 TLS 的标准算法,其密钥长度可以是 128 位、192 位、 256 位或者更长
非对称加密
在TLS里面,非对称加密算法主要用于密钥交换和身份认证,比较流行的算法包括: RSA
、 DSA
、 ECC
、 DH
其中 RSA
、 DSA
、 DH
都是基于数论的算法
ECC
是基于椭圆曲线的算法,ECC目前比较常用的两个曲线是 P-256(secp256r1,在 OpenSSL 称为 prime256v1)和 x25519
摘要算法
数字签名通常是使用单向加密的摘要算法,摘要算法主要负责计算内容的 哈希值(HMAC),这个哈希码是唯一的,并且无法反向推导。
密钥交换算法
密钥交换算法主要用于在握手阶段,客户端和服务器之间交换对称加密算法的密钥,常见的密钥交换算法包括 RSA
、 ECDHE
等
现代互联网都是使用 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 的一种。在握手阶段可以选择性地使用该功能
- 私有连接 :比如对称加密使用的
AES
和CHACHA20
(需要注意记录协议也可以提供不加密的封装,比如在握手阶段的 Hello 报文,意味着整个连接都是可定制化的,参数可选)
警报协议
警报协议用于在通信过程中发生错误时,向对方发送警报信息,比如握手失败、证书无效、加密失败等等,类似于HTTP的状态码
如:
- bad_record_mac :错误的MAC地址
- decode_error :解码异常
- protocol_version :表示旧版本不受支持
握手协议
握手协议是TLS的核心协议,用于在客户端和服务器之间进行身份认证、密钥交换、协商加密算法等等
握手协议的主要内容分为以下三点:
- 身份认证 :利用CA端进行身份认证,身份认证的过程会用到非对称加密算法,注意HTTPS支持客户端和服务端双向认证,默认是服务单单向认证,客户端认证是可选的
- 安全参数协商 : 保证被认证数据的机密性,需要用到比如哈希算法、密钥、加密算法等算法,对于数据加密处理
- 可靠协商 :可靠协商指的是防止数据传输过程中被篡改
握手协议定义了这些命令: ClientHello
、 SeverHello
、 Certificate
、 ServerKeyExchange
、 CertificateRequest
、 ServerHelloDone
、 ClientKeyExchange
、 CertificateVerify
、 ChangeCipherSpec
、 Finished
变更密码规范协议(Change Cipher Spec Protocol)
变更密码规范协议用于在握手过程中,通知对方之后的数据都将使用新的加密算法进行加密,这个协议只有一个命令: ChangeCipherSpec
Application Data 协议
Application Data 协议 用在通信阶段,封装了应用层的数据,通过 Record 协议 封装之后,再通过 TCP 协议 转发出去
此协议用于握手连接完成之后的数据传输规范,实际上可以看作是TLS和TCP的协议的对接
TLS 1.2 握手流程
HTTPS连接定义:
HTTPS交互流程图如下所示:
第一次握手
- 客户端发送一个
ClientHello
请求,同时传递一些必要参数:
client_version
:客户端支持的TLS版本client_random
:客户端生成的随机数,是后续对称加密密钥的必要参数之一session_id
:会话ID,如果客户端想要重用HTTPS会话,则在连接的时候需要携带此参数,否则为空cipher_suites
:客户端支持的加密套件compression_methods
:客户端支持的压缩会话列表extensions
:方便以后扩展新字段,该字段也是TLS 1.3的核心部分
- 服务器收到
ClientHello
请求之后,返回一个ServerHello
响应,同时传递一些参数:
server_version
:服务器选择合适的TLS版本server_random
:服务器生成的随机数,是后续对称加密密钥的关键参数cipher_suite
:从cipher_suites
选择合适的加密套件compression_method
:选择合适的压缩算法extensions
:扩展内容
第二次握手
第二次握手是从服务端开始的,服务端发送完
ClientHello
后,接着发送Certificate
,包括服务端的证书链,证书链中包含了服务端的公钥,客户端收到证书之后,会对证书进行校验数字证书传递之后,接下来是关键的一步,也就是密钥交换算法的协商(
Server Key Exchange
),密钥交换的算法实际上是对于会话密钥(对称加密方法)选择,也就是如何安全的把实际交互的对称密钥告知服务器,目前HTTPS采用ECDHE算法*如果本次HTTPS是双向认证,则可以通过
CertificateRequest
索要客户端证书,保证双向安全服务端发送
ServerHelloDone
告知客户端,服务端的握手阶段已经完成,等待客户端的响应
第三次握手
*如果服务端要求客户端提供证书,那么客户端会发送
Certificate
,证书中包含了客户端的公钥,服务端收到证书之后,会对证书进行校验在单向认证中,客户端生成客户端公钥,用非对称加密的公钥进行加密,然后发送
ClientKeyExchange
给服务端,到此,客户段两个“半片钥匙”都已经拿到*如果有客户端证书校验,则需要加一步
CertificateVerify
操作做完ECDHE传输之后,客户端和服务端各自持有 Client Params 和 Server Params 两个公钥,于是开始计算真实的会话密钥
- 双方用 Client Params 和 Server Params 两个公钥加复杂算法,计算出一个随机数 Pre-Master Key
- 双方用 Pre-Master Key 和 Client Random 、 Server Random 三个随机数,做伪随机数函数计算,生成最终的会话密钥 Master Key ,此外为保证安全性,还要再次加上摘要算法
会话密钥生成后,客户端就可以发送
Change Cipher Spec
告知服务端客户端再发送一个
Finished
消息( Encrypted Handshake Message ,所有数据摘要)把之前所有的消息做个摘要,用会话密钥加密,发送给服务端做个验证
第四次握手
服务端收到客户端的回应后,也会发送 Change Cipher Spec
和 Finished
消息,让客户端确认
两边核实无误,握手完成,开始正式的数据传输
TLS 1.3
TLS 1.3 中,废弃了 Session Ticket 机制和 Session ID 机制,改变了密钥派生的机制,废弃一大堆不安全的算法,并且握手信息也被部分的进行了加密。对于握手流程来说,由之前的2-RTT变成了1-RTT,大大提高了握手的速度
TLS 1.3 握手流程
握手协议主要分为三个流程:
- 密钥交换 :选择TLS协议版本和加密的算法,并且协商算法所需的参数。这段是明文传输的
- 服务器参数 :建立其他握手协议参数,例如是否需要认证客户端,支持何种应用层协议等
- 认证 :对服务器进行认证(包括可选的客户端认证)并且提供密钥确认和验证握手完整性功能