TLS协议中存在连接和会话的概念,会话上的加密信息是通过TLS握手协议进行协商的。
每次当给定的客户端与服务器经过完整的密钥交换并确立新的master_secret 时就会创建一个会话。一个给定的会话可以与多条连接关联。尽管给定会话中的所有连接均共享同一个master_secret,但是每个连接又都有它自己的加密密钥,MAC 密钥和IV。因此他们互相也是安全的。
当TLS的客户端和服务器开始进行TLS握手时,它们会就TLS协议标准、加密算法、认证算法进行协商,然后使用公钥加密等技术生成共享密钥。
TLS握手协议包含下面几个步骤:
- 交换hello报文信息协商算法信息、交换随机数、检查会话是否可复用;
- 交换必要的加密参数从而协商出主密钥;
- 交换证书和加密信息完成客户端和服务端的身份认证;
- 通过预主密钥(PreMasterKey)和双方随机数(client Random, Server Random)生成主密钥(MasterKey);
- 为记录层(Record Layer)提供安全参数
- 允许客户端和服务器验证是否生成相同的安全参数;此外还可以确认是否存在攻击者
实际在TLS握手交互过程中,根据选择的算法和配置情况交互报文略有不同。如:
- 客户端证书在大多数情况下并不用发送。这个与应用场景有关,但我们使用浏览器登录一个普通网页时并不需要双向认证。那么什么时候会进行双向认证呢? 一般是在重要场合(特别是涉及RMB的场合),这个时候需要双向认证,双方互相发送证书。
- 根据密钥配送算法的不同,TLS握手流程也不相同。关于密钥配送算法,在番外篇中进行介绍。
- 是否复用Session
下面分别对完整的TLS握手流程、复用session时的握手流程做一个介绍。
1. TLS 握手完整流程:
至此,TLS握手结束。
TLS完整握手流程如下:
对于可复用Session, TLS握手流程有所不同。
2. Session复用时TLS握手流程:
整个TLS 握手的开销可能非常巨大,无论从CPU 时间还是执行所需要的往返次数上讲均是如此。为了减少这种性能开销,在TLS中集成进了一种会话恢复机制。如果客户端与服务器已经通信过一次,则它们就可以跳过整个握手阶段而直接进行数据传输。握手中开销最昂贵的部分就是确立 pre_master_secret,它通常要求使用公用密钥加密。而经过恢复的握手允许新的连接使用上一次握手中确立的pre_master_secret。这就避免了公用密钥加密所需的计算开销昂贵的操作。
当客户端与服务器第一次进行交互时,它们创建一个新的连接和一个新的会话。如果务器准备恢复会话的话,就会在ServerHello 消息中给客户端一个session_id,并master_secret 缓存起来供以后引用。当这个客户端与服务器的创建新连接时,客户端在Client Hello报文中填充SessionID载荷,如果此项不为0,表示客户端想复用此SessionID的安全参数信息。服务端如果同意复用此Session,则可以在ServerHello中填入相同的SessionID值。之后客户端和服务端跳过后续握手流程,立即发送ChangeCipherSpec载荷,之后立即发送Finish载荷完成TLS的协商。
Session复用时TLS握手流程如下:
如果此sessionID在服务端中不可用,则服务端重新生成一个新sessionID,之后进行完整的TLS参数协商。
|