HTTP 协议及 TLS 协议


作者:Seiya

时间:2019年08月30日


前言


上图描述了 HTTP 的通信传输过程。首先作为发送端的客户端在应用层 (HTTP 协议)发出一个想看某个 Web 页面的 HTTP 请求。

接着,为了传输方便,在传输层(TCP 协议)把从应用层处收到的数 据(HTTP 请求报文)进行分割,并在各个报文上打上标记序号及端 口号后转发给网络层。

在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链 路层。这样一来,发往网络的通信请求就准备齐全了。

接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用 层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP 请求。

发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该 层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层 时会把对应的首部消去。

这种把数据信息包装起来的做法称为封装。





HTTP


超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。




HTTP 报文

用于 HTTP 协议交互的信息被称为 HTTP 报文。请求端(客户端)的 HTTP 报文叫做请求报文,响应端(服务器端)的叫做响应报文。 HTTP 报文本身是由多行数据构成的字符串文本。

HTTP 报文大致可分为报文首部和报文主体两块。两者由最初出现的空行来划分。通常,并不一定要有报文主体。


  • 请求报文

    HTTP 请求报文的结构如下:

    请求报文的首部内容由以下数据组成:

    • 请求行

      包含用于请求的方法,请求 URI 和 HTTP 版本。

    • 首部字段

      包含表示请求和响应的各种条件和属性的各类首部。一般有 4 种首部,分别是:通用首部、请求首部、响应首部和实体首部。

    • 其他

      可能包含 HTTP 的 RFC 里未定义的首部(Cookie 等)。


    举例如下:

  • 响应报文

    HTTP 响应报文的结构如下:

    响应报文的首部内容基本和请求报文一样,由状态行、首部字段、其他等字段组成:

    • 状态行

      包含表明响应结果的状态码,原因短语和 HTTP 版本。


    举例如下:





SSL / TLS

传输层安全性协议(英语:Transport Layer Security,缩写:TLS)及其前身安全套接层(英语:Secure Sockets Layer,缩写:SSL)是一种安全协议,目的是为互联网通信提供安全及数据完整性保障。


HTTPS 还是通过了 HTTP 来传输信息,但是信息通过 TLS 协议进行了加密。

TLS 协议位于传输层之上,应用层之下。首次进行 TLS 协议传输需要两个 RTT ,接下来可以通过 Session Resumption 减少到一个 RTT。




作用

不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险:

  • 窃听风险(eavesdropping):第三方可以获知通信内容;

  • 篡改风险(tampering):第三方可以修改通信内容;

  • 冒充风险(pretending):第三方可以冒充他人身份参与通信;


SSL/TLS协议是为了解决这三大风险而设计的,希望达到:

  • 所有信息都是加密传播,第三方无法窃听;

  • 具有校验机制,一旦被篡改,通信双方会立刻发现;

  • 配备身份证书,防止身份被冒充;




加密技术

在 SSL/TLS 中使用了两种加密技术,分别为:对称加密和非对称加密:

  • 对称加密

    对称加密就是两边拥有相同的秘钥,两边都知道如何将密文加密解密。

    这种加密方式固然很好,但是问题就在于如何让双方知道秘钥。因为传输数据都是走的网络,如果将秘钥通过网络的方式传递的话,一旦秘钥被截获就没有加密的意义的。


  • 非对称加密

    有公钥私钥之分,公钥所有人都可以知道,可以将数据用公钥加密,但是将数据解密必须使用私钥解密,私钥只有分发公钥的一方才知道。

    这种加密方式就可以完美解决对称加密存在的问题。假设现在两端需要使用对称加密,那么在这之前,可以先使用非对称加密交换秘钥。




基本的运行过程

SSL/TLS协议的基本思路是采用“公钥加密法”,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。


这里产生了两个问题:

  • 问题一:如何保证公钥不被篡改?

    解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。


  • 问题二:公钥加密处理起来比共享秘钥加密方式更为复杂,计算量太大,因此效率很低,如何减少耗用的时间?

    解决方法:每一次对话(session),客户端和服务器端都生成一个"对话密钥"(session key),用它来加密信息。由于"对话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"对话密钥"本身,这样就减少了加密运算的消耗时间。


基本运行过程如下:

  • 客户端向服务器端索要并验证公钥;

  • 双方协商生成"对话密钥";

  • 双方采用"对话密钥"进行加密通信;


上面过程的前两步,又称为"握手阶段"(handshake)。




TLS 握手过程


"握手阶段"涉及四次通信,需要注意的是,"握手阶段"的所有通信都是明文的:

  • 客户端发出请求(ClientHello)

    客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做 ClientHello 请求。在这一步,客户端主要向服务器提供以下信息:

    • 支持的协议版本,比如 TLS 1.0 版;

    • 一个客户端生成的随机数,稍后用于生成"对话密钥";

    • 支持的加密方法,比如 RSA 公钥加密;

    • 支持的压缩方法;


  • 服务器回应(SeverHello)

    服务器收到客户端请求后,向客户端发出回应,这叫做 SeverHello。服务器的回应包含以下内容:

    • 确认使用的加密通信协议版本,比如 TLS 1.0 版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信;

    • 一个服务器生成的随机数,稍后用于生成"对话密钥";

    • 确认使用的加密方法,比如 RSA 公钥加密;

    • 服务器证书;

    tips

    除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供"客户端证书"。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。


  • 客户端回应

    客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。

    如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息:

    • 一个随机数。该随机数用服务器公钥加密,防止被窃听;

    • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送;

    • 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验;


    上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。

    为什么一定要使用三个随机数?

    "不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。

    对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。

    pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"

    —— 来源 dog250


  • 服务器的最后回应

    服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息:

    • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送;

    • 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验;


至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。

最后更新时间: 2019-8-30 17:57:39