SSL握手过程详解

准备工作

【文档】对于一个协议来说,官方的RFC(Request for Comments)是最权威的。如果想要精通某个协议,详细阅读和理解RFC是必须的功课。SSL通信过程是TLS1.2的内容,RFC5246,应该死磕这个文档。

【工具】要想搞清楚通信握手过程的每一个细节,需要结合拦截的请求进行逐条的分析,此时必须使用wireshark这个工具,可以从这里下载。后面一些截图,即为该软件显示的通信信息。

【核心】SSL协议的核心是通过“握手”这个过程在服务器和客户端通过几个回合的沟通,以及非对称加密的方式各自生成主密钥(对话密钥,注意这个密钥从来不在网络上传播)。然后在握手之后的过程中,通过这个对话密钥进行加解密,并在网络上只传递密文。这篇就是逐条的讲述“握手(Handshake)”过程。

至于为什么不全程使用非对称加密方式处理数据,原因是非对称加密的性能比对称加密差很多,所以只要保证对称加密的主密钥安全,也就保证了通信过程的安全。

参考资料

如果说RFC是教材的话,以下一些大牛写的文章就是很好的教辅。

《使用wireshark观察SSL/TLS握手过程--双向认证/单向认证》
此文是主要参考资料,详细的讲述了每个环节,只是在此文基础上加入自己的理解形成了本篇。

《SSL协议详解》
此文对加密算法说的比较多,就握手协议来说不如上篇写的清楚,但在熟悉全过程的基础上,看懂也是没问题。

《图解SSL/TLS协议》
阮一峰大神的博客,主要在分析了DH算法和RSA算法的区别,也与我司环境一致,便于理解。

《非对称密码之DH密钥交换算法》
DH算法互相传递公钥,并通过对方的公钥和自己的密钥生成对话密钥,此文讲的图文并茂。

SSL握手过程

SSL的握手过程严格说是SSL协议的子协议,RFC5246(SSL V1.2)分为三个子协议,握手协议,记录协议(加密传输数据)和告警协议(用于告警和关闭连接)。握手过程实际就是握手协议的内容。

下图为wireshark中捕获的一个完整的握手过程,29为客户端,193为服务端。

SSL握手过程的命令

注意到这里有些在一行(叫做“多握手消息”),有些在多行,这个不是很清楚。

多握手消息

1. Client Hello

客户端发起会话,里面有以下两个信息最为重要

  1. 客户端随机数,用于生成主密钥;
  2. 客户端支持的密码套件列表,具体不展开,提供很多内容,关键看服务器端选哪个组合。

2. Server Hello

服务端产生第一次应答,里面同样有两个信息很重要

  1. 服务端随机数,用于生成主密钥;
  2. 确定密码套件(下图红框所示),这里就看出服务器将使用DH算法作为密钥交换算法,这在握手过程中会和RSA有所区别,注意这不是加密算法,AES_128_GCM才是,不在本文讨论范围内。
ServerHello内容

3. Certificate

服务端向客户端发送自己的证书,当前显示这是一个自签的证书(keytool工具生成)证书更多的是验证身份,其中包含了公钥,可用于RSA密钥交换算法的加密。

证书信息

4. Server Key Exchange

此处开始涉及到密钥交换算法,RSA不需要这步,而DH算法需要通过这步传递服务器公钥,并在客户端生成一个新的密钥对。仔细观察这部分内容和证书中的公钥似乎并不一样,这也是一个不太理解的地方

DH算法参数

5. Server Hello Done

一个空的指令,仅表示结束。

6. Client Key Exchange

在#4中获得了服务端的公钥,会根据DH算法生成一个新的密钥对(见参考资料)。客户端同样通过这个命令将密钥对里的客户端公钥发给服务端,仅限DH算法。

DH算法参数

7. Change Cipher Spec(客户端)

这步是一个提示,相当于客户端告诉服务端,改为加密的传输方式。这里隐含了一个操作,就是主密钥生成了!主密钥需要客户端随机数(#1),服务端随机数(#2),前主密钥(由#4获取的服务端公钥和客户端用其生成的密钥对中的的私钥生成),这三者共同生成,计算的方式可能和确定的密码套件有关。

8. Encrypted Handshake Message(客户端)

此步直译就是加密的握手信息,即从上一步开始,信息全部是加密的了,之前为明文。所以这步也代表着客户端握手过程的结束。

开始发送密文和加密的握手信息

9. Change Cipher Spec(服务端)

同样的,服务端也通过生成的前主密钥(自己的私钥和#6发来的客户端的公钥)加客户端随机数加服务端随机数生成主密钥。

10. Encrypted Handshake Message(服务端)

不再赘述。

开始发送密文
加密的握手信息

双向认证和单项认证

双向认证一般是在客户端验证服务端的基础上,加上服务端对客户端的验证,这要求

  1. 服务端明确提出要求,通过certificate request命令
  2. 客户端发送证书(certificate命令)和证书验证(certificate verify命令)

目前没有增加这块,所以暂时不写详细的实现了,可参阅其他资料。

你可能感兴趣的:(SSL握手过程详解)