目录
在这篇文章中,将会探索整个SSL/TLS握手过程,在此之前,先简述下最后这块内容的关键要点:
- TLS适用于对称密钥
- 对称密钥可以通过安全密钥交换算法共享
- 如果请求被截获,密钥交换可能会被欺骗
- 使用数字签名进行身份验证
- 证书颁发机构和信任链。
大多数现代浏览器都存有与Web服务器的最后一次连接的记录,如果最后一次连接是通过https进行的,那么下次浏览器将自动启动https请求而无需等待服务器。
TLS握手分为以下几个步骤:
- 客户端发送Hello报文
- 服务器接收Hello报文
- 共享证书和服务器密钥交换
- 更改密码规范
- 加密握手
客户端发送Hello报文
从这里开始,我将会重点讨论图片中标记为蓝色的主题,Client发送的Hello报文如下图所
我们知道TLS是在TCP之上实现的协议,TLS本身是一层协议并且它的底层叫做记录协议(Record protocol),这意味着所有数据都被记录。典型的记录格式如下
在图中,可以看出内容类型是Handshake,TLS版本1.0,数据长度为512.真实数据位于名为 Handshake Protocol:Client Hello的下拉列表中。我们继续观察下Client Hello中共享的数据。
客户端发送Hello报文的内容
浏览器与服务器共享以下详细信息
客户端版本
按优先顺序列出的客户端支持的协议版本,首选客户希望支持的最新协议版本。
客户端的随机数
一个32字节的数据,其中前4个字节表示epoch格式的当前日期时间。纪元时间是自1970年1月1日以来的秒数。其余28个字节由加密强随机数生成器生成(例如,Linux中的/dev/urandom
),客户端随机会在后面用到,请先记住这点。
会话id(Session id)
如果客户端第一次连接到服务器,那么这个字段就会保持为空。在上图中,您可以看到Session id正在给服务器发送东西,之所以会发生这种情况是由于我之前是通过https连接到github.com的,在此期间,服务器将使用Session id映射对称密钥,并将Session id存储在客户端浏览器中,为映射设置一个时间限。如果浏览器将来连接到同一台服务器(当然要在时间限到期之前),它将发送Session id,服务器将对映射的Session进行验证,并使用以前用过的对称密钥来恢复Session,这种情况下,就不需要完全握手。
客户端还将发送自己已经知道的密码套件列表,这个是由客户按优先顺序排列的,但完全由服务器来决定发送与否。TLS中使用的密码套件有一种标准格式。
- TLS:指使用的协议是TLS
- ECDHE:密钥交换算法
- ECDSA:签名或验证算法
- AES_128_GCM:称为批量加密算法。对称密钥加密算法是AES,密钥长度为128位,AES是块密码,也就是对输入的纯文本用固定长度的块来进行加密,加密后的每个块按再顺序发送,最后按类似的方式来进行解密。按标准规定,AES块固定长度为128位,但是输入的明文不要求必须是128的倍数,所以我们可能需要对最后一个块中进行填充,使其为固定的长度128位。除此之外,为了提高平均信息量,通常在加密之前会添加一些随机的比特到明文中,我们称为初始化矢量(IV)。有很多算法都可以在块上添加IV实现填充。在我们的例子Galois/Counter Mode(GCM)中用到过。或许详细解释GCM模式会使事情变得复杂,可见这并不是一个好主意。
SHA256:消息验证代码(MAC)算法。我们将详细讨论MAC。压缩数据
-
为了减少带宽,可以进行压缩。但从成功攻击TLS的事例