TLS 介绍
TLS (和 SSL) 协议位于应用程序协议层和 TCP/IP 层之间,可以在其中保护应用程序数据并将其发送到传输层。 由于协议在应用程序层和传输层之间工作,因此 TLS 和 SSL 可以支持多个应用程序层协议。
TLS 和 SSL 假定使用面向连接的传输(通常为 TCP), 可以预防如下风险:
- 消息篡改
- 消息拦截
- 消息伪造
TLS 握手 介绍
TLS 整个握手流程如下图所示
客户端请求(clinet hello)
这个阶段主要发送信息如下:
- 客户端支持的 TLS 版本号
- 客户端随机数Random
- 客户端支持的加密方法
- 客户端支持的压缩算法
服务端响应(server hello)
- 服务端支持的 TLS 版本号
- 服务端随机数Random
- 服务端支持的加密方法
- 服务端支持的压缩算法
服务端证书发送
服务端发送 server hello 后会发送证书,通常他们俩者在同一个网络包中,即同一个 TLS 记录层消息中。
证书验证(可选)
客户端拿到服务端证书,到证书办法机构的服务器(OCSP responder)验证证书是否可用
Client Key exchange
在此阶段客户端也会生成一个随机数,加上 clinet hello, server hello 生成的随机数一共三个随机数 作为 pre-master,发送给服务器,服务器端收到pre-master算出main master。而客户端当然也能自己通过pre-master算出main master。如此以来双方就算出了对称密钥。
客户端 finished
一个 Finished 消息一直会在一个 change cipher spec 消息后立即发送,以证明密钥交换和认证过程是成功的。一个 change cipher spec 消息必须在其它握手消息和结束消息之间被接收。
客户端握手结束通知, 表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验(使用HMAC算法计算收到和发送的所有握手消息的摘要,然后通过RFC5246中定义的一个伪函数PRF计算出结果,加密后发送。此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。)
服务端 Finished
服务端握手结束通知。
- 使用私钥解密加密的Pre-master数据,基于之前(Client Hello 和 Server Hello)交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key=Fuc(random_C, random_S, Pre-Master);
- 计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性;
- 发送一个 ChangeCipherSpec(告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了)
- 服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。
根据之前的握手信息,如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的Session Secret对数据进行加密传输了。
至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。