HTTPS通讯过程

这张图清楚的描述了客户端和服务器之间发生了什么。只要你理解了这张图,你就理解了HTTPS通讯过程。

(这张图取自https://www.researchgate.net/figure/HTTPS-message-sequence-diagram-with-detailed-TLS-handshaking-steps_fig1_306187575)

 

这张图包括了TCP握手过程和TLS握手过程,我们这里只看TLS握手过程。HTTPS实际就是HTTP+TLS. TLS的握手过程就是HTTPS的握手过程。

第一步:Client say Hello

         客户端率先发给服务器消息:“你好”。意思是,我准备和你通讯。这组“你好”的消息还包括下面这些信息。

  1. TLS Version. 这是我的TLS版本号
  2. A list of cipher suite 这些是客户端支持的加密算法
  3. SessionID 上图里没提。这是上一个连接的SessionID,如果是新建连接,它是空。
  4. A random number 这是一个随机数,后面要用到。
  5. A list of compression method 一组压缩方法,这不是重点。(感兴趣可看: https://tools.ietf.org/html/rfc3749#page-4)

这些信息在ClientHello的代码中是像下面这样的。

struct {

       ProtocolVersion client_version;

       Random random;

       SessionID session_id;

       CipherSuite cipher_suites<2..2^16-2>;

       CompressionMethod compression_methods<1..2^8-1>;

       select (extensions_present) {

           case false:

               struct {};

           case true:

               Extension extensions<0..2^16-1>;

       };

   } ClientHello;

第二步. 服务器回复一个ServerHello,其内容如下

          struct {

          ProtocolVersion server_version;

          Random random;

          SessionID session_id;

          CipherSuite cipher_suite;

          CompressionMethod compression_method;

          select (extensions_present) {

              case false:

                  struct {};

              case true:

                  Extension extensions<0..2^16-1>;

          };

      } ServerHello;

  1. TLS 版本
  2. 随机数,后面用
  3. 加密算法
  4. SessionID,上一个连接的SessionID。第一次建立连接,它是空
  5. 压缩方法。

第三步:服务器发送给客户端服务器的证书。

第四步:客户端验证服务器的证书。证书的验证过程:

                  https://www.weibo.com/ttarticle/p/show?id=2309404446091184570538

                  然后,客户端生成一个pre-master secret. 接着用服务器证书里的公钥加密这个pre-master secret,发送给服务器。

         我不知道怎么样用中文称呼pre-master secret才好,它其实就是一个随机数。

PreMasterSecret的结构如下,它包括2个byte的客户端协议版本号和46个byte的随机数,所以,pre-master secret一共是48个byte.

struct {

           ProtocolVersion client_version;

           opaque random[46];

       } PreMasterSecret;

第五步:服务器用自己的私钥解开pre-master secret, 然后用客户端的随机数、服务器的随机数和pre-master secret这三个参数计算出一个master secret作为对称加密的会话秘钥。

         客户端也用这三个参数计算出同样的master secret. 这样,客户端和服务器拥有了一样的会话秘钥。

master_secret的计算函数是下面这样子的。PRF是伪随机函数(pseudo-random function),它接受3个参数,第二个参数是个简单的写死的字符串。

master_secret = PRF(pre_master_secret, 
                     "master secret", 
                      ClientHello.random + ServerHello.random)

接下来,客户端和服务器就会协商出一种加密算法并用这种算法加密消息,后续的应用层面的数据通讯便都用对称加密的方式通讯。

一些问题:

  1. 网络监听者能破解pre-master secret吗?

不能,因为他没有私钥。所以,他也无法知道对称秘钥。

  1. 客户端用来加密的公钥可靠吗?

可靠。因为证书是经过客户端验证的,验证成功则表明证书合法,证书合法则公钥可靠。

  1. 为什么需要随机数?

是为了防止重放攻击。网络攻击者虽然不能破解数据包,但他可以重新发送数据包,以达到欺骗系统的目的。使用随机数可以防止这种情况发生,如果网络攻击者重发握手数据包,则服务器会生成新的随机数,服务器端的master_secret会不一样。被中间人重发的应用层面的数据包服务器就不会认得,连接中断。

  1. 如果浏览器被控制和破解了,pre-master secret是不是泄露了?

应该是的。但这种破解已经不是“中间人攻击”范畴了。现在的机制,是为了防止中间人攻击。

参考:https://tools.ietf.org/html/rfc2246#page-11

原文地址:https://www.cnblogs.com/dapplehou/p/12737897.html