Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@YanceyOfficial
Last active March 27, 2022 16:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YanceyOfficial/6b0bd5579f7fb244044541b7e38e6acc to your computer and use it in GitHub Desktop.
Save YanceyOfficial/6b0bd5579f7fb244044541b7e38e6acc to your computer and use it in GitHub Desktop.
TLS 握手小结

SSL 握手过程

只验证服务器的 SSL 握手过程

1. Client Hello

SSL 客户端通过 Client Hello 消息向 SSL 服务端发送:

  • 支持的 SSL 版本
  • 客户端生成的一个用于生成主密钥(master key)的 32 字节的随机数(主密钥由客户端和服务端的随机数共同生成)
  • 会话 ID
  • 加密套件
    • 加密算法
    • 密钥交换算法
    • MAC 算法
    • 加密方式(流, 分组)
  • 压缩算法(如果支持压缩的话)

2. Server Hello

SSL 服务器确定本次通信采用的 SSL 版本和加密套件, 并通过 Server Hello 消息通知给 SSL 客户端. 如果 SSL 服务器允许 SSL 客户端在以后的通信中重用本次会话, 则 SSL 服务器会为本次会话分配会话 ID, 并通过 Server Hello 消息发送给 SSL 客户端.

  • 服务端采纳的本次通讯的 SSL 版本
  • 服务端生成的一个用于生成主密钥(master key)的 32 字节的随机数(主密钥由客户端和服务端的随机数共同生成)
  • 会话 ID
  • 服务端采纳的用于本次通讯的加密套件(从客户端发送的加密套件列表中选出了一个)
    • 加密算法
    • 密钥交换算法
    • MAC 算法
    • 加密方式(流, 分组)
  • 压缩算法(如果支持压缩的话)

3. Certificate

SSL 服务器将携带自己公钥信息的数字证书和到根 CA 整个链发给客户端通过 Certificate 消息发送给 SSL 客户端(整个公钥文件都发送过去), 客户端使用这个公钥完成以下任务:

  • 客户端可以使用该公钥来验证服务端的身份, 因为只有服务端有对应的私钥能解密它的公钥加密的数据
  • 用于对 premaster secret 进行加密, 这个 premaster secret 就是用客户端和服务端生成的 Random 随机数来生成的, 客户端用服务端的公钥对其进行了加密后发送给服务端

4. Server Key Exchange

密钥交换阶段(可选步骤), 之所以说是可选步骤, 是因为只有在下列场景下这个步骤才会发生

  • 协商采用了 RSA 加密, 但是服务端的证书没有提供 RSA 公钥
  • 协商采用了 DH 加密, 但是服务端的证书没有提供 DH 参数
  • 协商采用了 fortezza_kea 加密, 但是服务端的证书没有提供参数 总结来说, Server Key Exchange 这个步骤是对上一步 Certificate 的一个补充, 为了让整个 SSL 握手过程能正常进行

5. Server Hello Done

SSL 服务器发送 Server Hello Done 消息, 通知 SSL 客户端版本和加密套件协商结束

6. Client Key Exchange

SSL 客户端验证 SSL 服务器的证书合法后, 利用证书中的公钥加密 SSL 客户端随机生成的 premaster secret (通过之前客户端, 服务端分别生成的随机数生成的), 并通过 Client Key Exchange 消息发送给 SSL 服务器. 注意, 这一步完成后, 客户端和服务端都已经保存了主密钥(之所以这里叫预备主密钥, 是因为还没有投入使用). 这个主密钥会用于之后的 SSL 通信数据的加密

7. Change Cipher Spec

SSL 客户端发送 Change Cipher Spec 消息, 通知 SSL 服务器后续报文将采用协商好的主密钥和加密套件进行加密和 MAC 计算.

8. Finished

SSL 客户端计算已交互的握手消息(除 Change Cipher Spec 消息外所有已交互的消息)的 Hash 值, 利用协商好的密钥和加密套件处理 Hash 值(计算并添加 MAC 值, 加密等), 并通过 Finished 消息 发送给 SSL 服务器. SSL 服务器利用同样的方法计算已交互的握手消息的 Hash 值, 并与 Finished 消息的解密结果比较, 如果二者相同, 且 MAC 值验证成功, 则证明密钥和加密套件协商成功.

9. Change Cipher Spec

同样地, SSL 服务器发送 Change Cipher Spec 消息, 通知 SSL 客户端后续报文将采用协商好的密钥和加密套件进行加密和 MAC 计算.

10. Finished

SSL 服务器计算已交互的握手消息的 Hash 值, 利用协商好的密钥和加密套件处理 Hash 值(计算并添加 MAC 值, 加密等), 并通过 Finished 消息发送给 SSL 客户端. SSL 客户端利用同样的方法计算已交互的握手消息的 Hash 值, 并与 Finished 消息的解密结果比较, 如果二者相同, 且 MAC 值验证成功, 则证明密钥和加密套件协商成功.

SSL 客户端接收到 SSL 服务器发送的 Finished 消息后, 如果解密成功, 则可以判断 SSL 服务器是数字证书的拥有者, 即 SSL 服务器身份验证成功, 因为只有拥有私钥的 SSL 服务器才能从 Client Key Exchange 消息中解密得到 premaster secret, 从而间接地实现了 SSL 客户端对 SSL 服务器的身份验证.

验证服务器和客户端的 SSL 握手过程

验证服务器和客户端的 SSL 握手过程只验证服务器的 SSL 握手过程整体过程类似, 只是多了服务端向客户端要求发送证明客户端身份的证书, 以及客户端发送证书的过程.

1. Client Hello

SSL 客户端通过 Client Hello 消息向 SSL 服务端发送:

  • 支持的 SSL 版本
  • 客户端生成的一个用于生成主密钥(master key)的 32 字节的随机数(主密钥由客户端和服务端的随机数共同生成)
  • 会话 ID
  • 加密套件
    • 加密算法
    • 密钥交换算法
    • MAC 算法
    • 加密方式(流. 分组)
  • 压缩算法(如果支持压缩的话)

2. Server Hello

SSL 服务器确定本次通信采用的 SSL 版本和加密套件, 并通过 Server Hello 消息通知给 SSL 客户端. 如果 SSL 服务器允许 SSL 客户端在以后的通信中重用本次会话, 则 SSL 服务器会为本次会话分配 会话 ID, 并通过 Server Hello 消息发送给 SSL 客户端.

  • 服务端采纳的本次通讯的 SSL 版本
  • 服务端生成的一个用于生成主密钥(master key)的 32 字节的随机数(主密钥由客户端和服务端的随机数共同生成)
  • 会话 ID
  • 服务端采纳的用于本次通讯的加密套件(从客户端发送的加密套件列表中选出了一个)
    • 加密算法
    • 密钥交换算法
    • MAC 算法
    • 加密方式(流. 分组)
  • 压缩算法(如果支持压缩的话)

3. Certificate

SSL 服务器将携带自己公钥信息的数字证书和到根 CA 整个链发给客户端通过 Certificate 消息发送给 SSL 客户端(整个公钥文件都发送过去), 客户端使用这个公钥完成以下任务:

  • 客户端可以使用该公钥来验证服务端的身份, 因为只有服务端有对应的私钥能解密它的公钥加密的数据
  • 用于对 premaster secret 进行加密, 这个 premaster secret 就是用客户端和服务端生成的 Ramdom 随机数来生成的, 客户端用服务端的公钥对其进行了加密后发送给服务端

4. Server Key Exchange

密钥交换阶段(可选步骤), 之所以说是可选步骤, 是因为只有在下列场景下这个步骤才会发生

  • 协商采用了 RSA 加密, 但是服务端的证书没有提供 RSA 公钥
  • 协商采用了 DH 加密, 但是服务端的证书没有提供 DH 参数
  • 协商采用了 fortezza_kea 加密, 但是服务端的证书没有提供参数 总结来说, Server Key Exchange 这个步骤是对上一步 Certificate 的一个补充, 为了让整个 SSL 握手过程能正常进行

5. Client Certificate Request

服务器可以向客户发送 certificate_request 请求证书, 即服务端需要客户端证明自己的身份

6. Server Hello Done

SSL 服务器发送 Server Hello Done 消息, 通知 SSL 客户端版本和加密套件协商结束

7. Client Certificate

客户端(浏览器)向服务器发送自己的客户端证书, 以证明自己的身份

8. Client Key Exchange

SSL 客户端验证 SSL 服务器的证书合法后, 利用证书中的公钥加密 SSL 客户端随机生成的 premaster secret (通过之前客户端. 服务端分别生成的随机数生成的), 并通过 Client Key Exchange 消息发送给 SSL 服务器. 注意, 这一步完成后, 客户端和服务端都已经保存了主密钥(之所以这里叫预备主密钥, 是因为还没有投入使用). 这个主密钥会用于之后的 SSL 通信数据的加密

9. Certificate Verify

客户可能发送 client_verify 报文来校验客户端发送的证书

10. Change Cipher Spec

SSL 客户端发送 Change Cipher Spec 消息, 通知 SSL 服务器后续报文将采用协商好的主密钥和加密套件进行加密和 MAC 计算.

11. Finished

SSL 客户端计算已交互的握手消息(除 Change Cipher Spec 消息外所有已交互的消息)的 Hash 值, 利用协商好的密钥和加密套件处理 Hash 值(计算并添加 MAC 值. 加密等), 并通过 Finished 消息发送给 SSL 服务器. SSL 服务器利用同样的方法计算已交互的握手消息的 Hash 值, 并与 Finished 消息的解密结果比较, 如果二者相同, 且 MAC 值验证成功, 则证明密钥和加密套件协商成功.

13. Change Cipher Spec

同样地, SSL 服务器发送 Change Cipher Spec 消息, 通知 SSL 客户端后续报文将采用协商好的密钥和加密套件进行加密和 MAC 计算.

13. Finished

SSL 服务器计算已交互的握手消息的 Hash 值, 利用协商好的密钥和加密套件处理 Hash 值(计算并添加 MAC 值. 加密等), 并通过 Finished 消息发送给 SSL 客户端. SSL 客户端利用同样的方法计算已交互的握手消息的 Hash 值, 并与 Finished 消息的解密结果比较, 如果二者相同, 且 MAC 值验证成功, 则证明密钥和加密套件协商成功.

SSL 客户端接收到 SSL 服务器发送的 Finished 消息后, 如果解密成功, 则可以判断 SSL 服务器是数字证书的拥有者, 即 SSL 服务器身份验证成功, 因为只有拥有私钥的 SSL 服务器才能从 Client Key Exchange 消息中解密得到 premaster secret, 从而间接地实现了 SSL 客户端对 SSL 服务器的身份验证.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment