SSL/TLS协议

SSL/TLS协议

SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。NetScape(网景)公司在1994设计了SSL协议。

IETF 就在把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

SSL协议的三个特性

  1. 保密:在握手协议中定义了会话**后,所有的消息都被加密。
  2. 鉴别:可选的客户端认证,和强制的服务器端认证。
  3. 完整性:传送的消息包括消息完整性检查(使用MAC)。

这三个特性就可以解决明文传输带来的危害,窃听风险(被人监听网络交互内容),篡改风险(修改你的交互内容)冒充风险

SSL的工作原理

握手协议(Handshake protocol)
记录协议(Record protocol)
警报协议(Alert protocol)

握手协议:

握手协议是客户机和服务器用SSL连接通信时使用的第一个子协议,握手协议包括客户机与服务器之间的一系列消息。SSL中最复杂的协议就是握手协议。该协议允许服务器和客户机相互验证,协商加密和MAC算法以及保***,用来保护在SSL记录中发送的数据。握手协议是在应用程序的数据传输之前使用的。

记录协议 :

记录协议在客户机和服务器握手成功后使用,即客户机和服务器鉴别对方和确定安全信息交换使用的算法后,进入SSL记录协议,记录协议向SSL连接提供两个服务:
  (1)保密性:使用握手协议定义的秘***实现
  (2)完整性:握手协议定义了MAC,用于保证消息完整性

警报协议:

客户机和服务器发现错误时,向对方发送一个警报消息。如果是致命错误,则算法立即关闭SSL连接,双方还会先删除相关的会话号,秘密和**。每个警报消息共2个字节,第1个字节表示错误类型,如果是警报,则值为1,如果是致命错误,则值为2;第2个字节制定实际错误类型。

在了解基本的运行方式之前,还有几个密码学的概念需要了解:

  • 密码学(cryptography):目的是通过将信息编码使其不可读,从而达到安全性。
  • 明文(plain text):发送人、接受人和任何访问消息的人都能理解的消息。
  • 密文(cipher text):明文消息经过某种编码后,得到密文消息。
  • 加密(encryption):将明文消息变成密文消息。
  • 解密(decryption):将密文消息变成明文消息。
  • 算法:取一个输入文本,产生一个输出文本。
  • 加密算法:发送方进行加密的算法。
  • 解密算法:接收方进行解密的算法。
  • **(key):只有发送方和接收方理解的消息
  • 对称**加密(Symmetric Key Cryptography):加密与解密使用相同**。
  • 非对称**加密(Asymmetric Key Cryptography):加密与解密使用不同**。

下面就可以切入比较复杂的SSL/TLS的握手过程

SSL/TLS 握手过程

“握手阶段”涉及四次通信。需要注意的是,”握手阶段”的所有通信都是明文的。

SSL/TLS协议

第一次通信 客户端发出请求(ClientHello):

客户端先向服务器发出加密通信的请求,这被叫做ClientHello请求。包含的信息为:

  • SSL/TLS的版本信息(应该是最大的版本信息),是为了同服务器的对应的版本想匹配
  • 32字节的随机数(用于后续的秘钥的生成,加大第三方的**难度)
  • 客户端支持的加密套件 cipher suites 列表,认证算法 Au (身份验证)、**交换算法 KeyExchange(**协商)、对称加密算法 Enc (信息加密)和信息摘要 Mac(完整性校验);(让服务端选取对应的加密算法)
  • 支持的压缩算法 compression methods 列表,用于后续的信息压缩传输;(列表形式,让服务端选取对应的压缩的方式)
  • 扩展字段 extensions(后来添加的),支持协议与算法的相关参数以及其它辅助信息等,常见的 SNI(Server Name Indication,用于解决一个服务器智能有一个证书的问题,允许客户端向服务器提供它所请求的域名) 就属于扩展字段,SNI (Server Name Indication)是用来改善服务器与客户端 SSL (Secure Socket Layer)和 TLS (Transport Layer Security) 的一个扩展。主要解决一台服务器只能使用一个证书(一个域名)的缺点,随着服务器对虚拟主机的支持,一个服务器上可以为多个域名提供服务,因此SNI必须得到支持才能满足需求。1个服务器可能为上千个域名提供服务,不可能将所有证书都发送给客户端,让客户端一一验证,找到与请求域名对应的证书。SNI的设计目的是为了让服务器根据请求来决定为哪个域服务,这个信息通常从HTTP请求头获得。

第二次通信 服务器回应(SeverHello):

其实就是别人给你打了招呼,不管认不认识,你总得回应一下,介绍一下自己,才能确定有没有进一步交流的必要

  • 选择使用的TLS/SSL协议版本 version,如果没有支持的共同的版本,那就拜拜了
  • 选择客户端对应的加密套件
  • 选择客户端对应的压缩套件
  • 32字节的随机数(多一个暗号,就更安全一些,也是为了对话**)
  • 服务器证书(把证书发给客户端)
  • 请求客户端证书(服务端可能会要求客户自身进行验证,注意可能)

第三次通信 客户端回应:

客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。
如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送回应。

  • 合法性验证通过之后,客户端计算产生随机数字 Pre-master(第三个随机数),并用证书公钥加密,发送给服务器;
  • 此时客户端已经获取全部的计算协商**需要的信息,将三个随机数合成秘钥,客户端通知服务器后续的通信都采用协商的通信**和加密算法进行加密通信(此步骤就产生了客户端的”会话**”。);
  • 结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商** session secret 与算法进行加密,然后发送给服务器用于数据与握手验证;
  • 如果需要客户端证书的话,客户端会在这一步发送证书及相关信息

第四次通信 服务器的最后回应:

服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的”会话**”。然后,向客户端最后发送下面信息。

  • 编码改变通知,表示随后的信息都将用双方商定的加密方法和**发送。
  • 计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和**正确性;
  • 服务器也结合所有当前的通信参数信息生成一段数据并采用协商** session secret 与算法加密并发送到客户端;

客户端计算所有接收信息的 hash 值,并采用协商**解密 encrypted_handshake_message,验证服务器发送的数据和**,验证通过则握手完成;(此次处理仅发生在客户端,并不是一次通信)

session ID/session ticket

为了加快建立握手的速度,减少协议带来的性能降低和资源消耗(主要提高再次握手的效率),TLS 协议有两类会话缓存机制:会话标识 session ID 与会话记录 session ticket。

session ID 由服务器端支持,协议中的标准字段,因此基本所有服务器都支持,服务器端保存会话ID以及协商的通信信息,Nginx 中1M 内存约可以保存4000个 session ID 机器相关信息,占用服务器资源较多;

session ticket 需要服务器和客户端都支持,属于一个扩展字段,支持范围约60%(无可靠统计与来源),将协商的通信信息加密之后发送给客户端保存,**只有服务器知道,占用服务器资源很少。

二者都存在的情况下,优先使用 session_ticket。

session ID

  • 如果客户端和服务器之间曾经建立了连接,服务器会在握手成功后返回 session ID,并保存对应的通信参数在服务器中;
  • 如果客户端再次需要和该服务器建立连接,则在 client_hello 中 session ID 中携带记录的信息,发送给服务器;
  • 服务器根据收到的 session ID 检索缓存记录,如果没有检索到货缓存过期,则按照正常的握手过程进行;
  • 如果检索到对应的缓存记录,则返回 change_cipher_spec 与 encrypted_handshake_message 信息,两个信息作用类似,encrypted_handshake_message 是到当前的通信参数与 master_secret的hash 值;(如果有缓存验证加密数据)
  • 如果客户端能够验证通过服务器加密数据,则客户端同样发送 change_cipher_spec 与 encrypted_handshake_message 信息;
  • 服务器验证数据通过,则握手建立成功,开始进行正常的加密数据通信。(当然不通过,接着握手,通过了就直接通信,提高效率)

session ticket

  • 如果客户端和服务器之间曾经建立了连接,服务器会在 new_session_ticket 数据中携带加密的 session_ticket 信息,客户端保存;
  • 如果客户端再次需要和该服务器建立连接,则在 client_hello 中扩展字段 session_ticket 中携带加密信息,一起发送给服务器;
  • 服务器解密 sesssion_ticket 数据,如果能够解密失败,则按照正常的握手过程进行;
  • 如果解密成功,则返回 change_cipher_spec 与 encrypted_handshake_message 信息,两个信息作用与 session ID 中类似;
  • 如果客户端能够验证通过服务器加密数据,则客户端同样发送 change_cipher_spec与encrypted_handshake_message 信息;
  • 服务器验证数据通过,则握手建立成功,开始进行正常的加密数据通信。

数据加密通信过程

  • 对应用层数据进行分片成合适的 block;
  • 为分片数据编号,防止重放攻击;
  • 使用协商的压缩算法压缩数据;
  • 计算 MAC 值和压缩数据组成传输数据;
  • 使用 client encryption key 加密数据,发送给服务器 server;
  • server 收到数据之后使用 client encrytion key 解密,校验数据,解压缩数据,重新组装。(反之亦然)

补充:
**Key 经过12轮迭代计算会获取到12个 hash 值,分组成为6个元素,client Mac key, server Mac key,client encryption key,server encryption key,client IV,server IV;
mac key、encryption key 和 IV 是一组加密元素,分别被客户端和服务器使用,但是这两组元素都被两边同时获取;
客户端使用 client 组元素加密数据,服务器使用 client 元素解密;服务器使用 server 元素加密,client 使用 server 元素解密;
双向通信的不同方向使用的**不同,**通信至少需要**两次;

encryption key 用于对称加密数据;
IV 作为很多加密算法的初始化向量使用,具体可以研究对称加密算法;
Mac key 用于数据的完整性校验;