问题
HTTPS在每次请求的时候都会携带证书吗
答案
不会,为了避免资源损耗导致的效率低下问题,通过session id 或 session ticket 可以将已经建立的SSL会话信息缓存起来,在SSL握手阶段发送该信息给服务器校验,如果校验通过就可以复用旧密钥,而不用再次生成密钥。
HTTPS握手过程

image.png
- SSL握手,客户端首先发送client hello请求,里面有TLS版本,加密组件,和一个随机数
- 服务器收到client hello 后,返回一个server hello响应,里面有TLS版本,从client hello请求的加密组件中选择的要使用的加密组件,以及一个随机数
- 服务器将证书发送给客户端
- 服务器发送server hello done报文到客户端
- 客户端验证服务器的证书,如果验证不通则握手失败,如果验证通过,客户端会发送 client key exchange 报文
- client key exchange报文的内容取决于密钥交换算法,如果密钥交换算法是RSA,那么这里客户端接收到 server hello done 之后,会通过Client随机生成46字节+2字节的client_version作为 pre master key,并用证书中的公钥将其加密发送到服务器
- 如果密钥交换算法是DH(严格来说DH属于密钥协商算法),那么客户端会生成一个大随机数,并以此计算一个公钥,并通过client key exchange报文将计算的公钥发送至服务端;并且服务端会生成一个大随机数,并以此计算一个公钥,然后将该公钥通过 Server Key Exchange 报文发送到客户端;之后客户端和服务端会通过接收到的对方的公钥分别计算pre master key(DH算法可以保证这样两端计算得到的 pre maser key都是一致的)
- 所有的密钥交换算法或密钥协商算法都会得到 pre master key,然后 pre masert key 结合 client hello中的随机数、server hello 中的随机数生成master secret,最后利用 master secret生成对称加密的密钥。之后,就是用该密钥进行加密通信。
注意点
server key exchange报文不是所有情况下都会发送的,如果密钥生成不需要服务器生成的信息,那么握手阶段就只会有 client key exchange报文。
-
client hello 中会携带一个 session id 发送至客户端,它是 SSL 会话的一个标识,初次连接时该id为空,服务器端会校验该id,如果服务器端检测到session cache中有这个session id的记录,那么客户端和服务器就可以直接使用之前的密钥通信,而不用再进行SSL握手。
server hello可以对client hello中的session id实施以下几种策略:- 恢复session id,即使用之前缓存的密钥进行通信
- 新的session id,如果client hello中的 session id是空值,那么服务器会返回与一个;如果服务器没有在缓存中找到对应的session id,会返回一个新的session id
- 服务器不使用旧密钥,将 session id置为空
除了session id之外,还有session tickets机制,该机制与session id将信息保存在服务器不同,而是将信息保存在客户端。session ticket 通过服务器将会话密钥等信息加密后传输给客户端保存,待下次客户端发送过来后直接进行解密验证。