HTTP

HTTP: hyper text transfer protocol(超文本传输协议)

HTTP 普遍使用于各网站,基于 TCP ,是一个无连接、无状态的协议,速度较快,但是传输数据的时候使用的都是明文传输,所以在安全级别比较高的场景不合适,所以就衍生出基于 HTTP 的较安全的协议 HTTPS 。

HTTP 是基于 TCP 协议的,工作在应用层。 TCP 协议是一种面向连接的协议,工作在传输层,TCP 通过自己的三次握手、四次挥手机制很大程度上保证了数据传输的可靠性,所以 HTTP 广泛应用于网站的建设上,并且 HTTP 通过其请求头、请求内容等方式提供了比较丰富的功能。

请求头

POST /getCommRec HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: ichp.wuruoye.com
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
Content-Length: 48

{"token":"eb0e4d9e-4888-11e8-8bee-525400ae50a0"}

如上是一个请求的示例,包含请求头和请求主体,请求头每行代表一种信息,请求头与请求主体中间有一行空行代表请求头的结束。

每一行代表一种配置,如第一行,规定了请求方法是 POST ,请求的 URL 是网站根目录/getCommRec,使用的协议是HTTP/1.1,即 HTTP 1.1 版本。第二行告诉服务端使用的是 json 的方式传输数据,字符编码格式为 utf-8 ,之后的等等。

请求方法

一般 HTTP 提供的请求方法有 GET POST HEADER PUT DELETE OPTIONS 等。

每种请求方法都有它自己的含义,但是这并不是规定性的东西,在实际开发中完全可以只使用其中的一种或者几种完成所有的工作,只需要服务端能够给出正确的应答就行。但是在 RESUTFUL 编程的规范中,应该根据不同的请求目的使用不同的请求方法,如下介绍:

GET

GET 方法一般表示向服务器请求某些数据,其参数会直接显示在 URL 中,以?arg1=value1&arg2=value2的方式加载原本 URL 的末尾。

POST

POST 方法表示请求服务器新增数据,其表单中的参数会保存在请求体中。

PUT

PUT 方法表示请求服务器更新某些数据,参数使用与 POST 一致。

DELETE

DELETE 方法表示请求服务器删除某些数据,参数使用与 POST 一致。

在 RESTFUL 编程的规范中,应该只使用请求方法表示动作,并且在 URL 中不应该包含表示动作的单词,而应该只是表示某个数据实体的名词。如GET /getUser GET /addUser GET /updateUser GET /deleteUser 这些使用应该尽量避免,并且应该使用GET /user POST /user PUT /user DELETE /user的方式发起 HTTP 请求。

响应头

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 27 Apr 2018 00:58:42 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 102
Connection: close

{"token": "20f8688a-49b6-11e8-8bee-525400ae50a0", "uid": 1119, "msg": "login successfully", "code": 0}

这是一个响应的基本格式,包含前面的响应头以及后面的响应主体。

响应码

响应码是一个三位数,然后每个百位数代表一种请求结果,后面的十位数和个数代表具体的说明,如:

  1. 1XX

    服务端临时响应,表示客户端还要继续其请求操作。

  2. 2XX

    请求成功。

  3. 3XX

    重定向。

  4. 4XX

    客户端请求有误。

  5. 5XX

    服务端处理有误。

目前为止相应码使用到的还比较少,大部分是预留的。

HTTP 的安全

虽然 HTTP 提供了比较完整的功能,但是使用 HTTP 传输的数据没有任何加密处理,任何拦截者在数据从客户端发送到服务端的过程中(中间要经过多个路由器、网关等设备)对这段数据提取出来进行处理,都能得到其中的真实数据,这就使得 HTTP 不能用来传送比较隐秘的数据,但是这种要求肯定是存在的,所以解决方案就是对 HTTP 生成的数据使用 SSL/TLS 协议封装,由于 SSL/TLS 提供了安全的数据传输方式,所以 HTTP 传输的数据就变得安全了,而它们两者结合就成为了另一个东西,HTTPS 。

HTTPS 由两个协议组成,HTTP 和 SSl/TLS 。HTTP 负责数据的传输,SSL/TLS 负责数据的安全。

HTTP 默认使用 80 端口,HTTPS 默认使用 443 端口,当客户端请求服务端的 443 端口的时候,就会自动进行 SSL/TLS 的验证等一系列安全操作。

HTTPS

HTTPS: hyper text transfer protocol over secure socket layer(基于 SSL 的 HTTP)

HTTPS 的基本原理就是,通过一种安全的方法传输 HTTP 报文,从而达到安全的效果,比如发送方对 HTTP 报文加密,传输这个密文,然后接收方再对这个密文解密,得到实际的数据。HTTPS 就是通过 SSL(或者 TLS)来进行加密的,所谓 HTTPS 的原理,就是 HTTP 的外面覆盖上一层 SSL/TLS 来加密的过程,因为涉及到加密,所以就涉及到密码学中的对称加密、非对称加密、数字证书等一系列的东西。

SSL/TLS 和 HTTP 共同组成了 HTTPS ,其中 HTTP 完成了数据的传输,SSL/TLS 完成了数据的加密,二者共同构成了一个更加安全的网络环境。所以在了解 HTTPS 的工作的时候,更关注的是了解 SSL/TLS 的工作,SSL/TLS 利用自己的握手机制使得客户端和服务端在在这个过程中互相交流得到了密钥,在数据传输的过程中 SSL/TLS 会对 HTTP 产生的报文使用这个密钥加密,所以对于 SSL/TLS 来说主要的工作还是握手阶段是如何完成的。而这个阶段比较复杂,使用到的东西比较多,有密钥、公钥、私钥、指纹、数字证书等。

密钥

密钥是一种加密方式,比如一个对称加密,加密的过程是将所有的字符都做 +4 处理,使“abc”变成了“efg”,这里的 4 就是密钥。

公钥、私钥

对于非对称加密来说,它有两个密钥,分为公钥和私钥,使用公钥加密的数据只能使用私钥解开,同时使用私钥加密的数据只能使用公公钥解开,一般情况下公钥会广泛地发送给所有的客户端,而私钥只会在服务端保留,只要私钥不泄漏,那么这个加密方式就是安全的。

指纹

指纹就是采用某种 Hash 算法对某段数据取的 Hash 值经过加密处理之后的一段数据,以确保这段数据没有被修改过。比如在这个过程中,使用私钥对公钥的 Hash 值加密,并传给客户端验证,以保证在传输过程中公钥没有被修改。

数字证书

首先要说明一下,在生成这里的数字证书的过程中,有两对私钥和公钥参与,分别是证书制作方的公私钥和服务端的公私钥,在制作数字证书的时候,会讲服务端公钥加入进去,同时还附有证书制作方的信息(机构名等),还有证书本身的信息(如有效时间,对应域名等),还有服务端公钥的指纹(使用制作方私钥加密的公钥的 Hash 值)。

SSL/TLS 握手过程

1. 客户端发起连接请求

当客户端需要向服务端请求数据的时候,会向服务端发起一个连接请求,同时附上自己支持的加密算法,hash 算法,压缩格式等需要双方统一的配置性问题。

同时在这个过程中客户端会生成一个随机数 A ,并且发送个服务端。

2. 服务端返回证书

服务端接收到客户端的请求之后,从客户端发送的一系列算法中选择其中一个并返回。同时服务器会将自己的数字证书发送给客户端。

这个过程中服务端也会生成一个随机数 B ,并发送给客户端。这是服务端和客户端各有各有两个随机数 A B 。

数字证书
来源

数字证书可以是某个权威的证书颁发机构颁发的,也可以是非权威机构(如用户自己)使用生成器(如 openssl )生成的。

内容

数字证书包括几个内容:

  1. 与服务器端的私钥对应的公钥,用于之后与服务器的加密沟通
  2. 使用颁发机构的私钥对这个公钥的 Hash 值进行的加密结果,可以称作“指纹”
  3. 当前证书的颁发机构、有效时间、对应的域名、对公钥使用的 Hash 算法等

3. 客户端验证证书并发送随机数

客户端首先收到服务器端发送过来的一系列的加密算法的规定。

然后接收到服务端发来的证书,首先会对证书的颁发机构进行检测,因为客户端本身会内置所有权威机构的信息,所以只要服务端的证书是权威机构颁发的,就能够找到这个权威机构的公钥,如果找不到,就会提示用户证书非权威机构颁发,不可靠之类的,让用户确认继续操作。否则的话就继续检测证书的其他有效信息,如是否在有效期内,是否与证书内规定的域名相同等,检测到不对等的信息,也会提示用户不安全。监测到这些信息没问题之后,就会取出这个与这个权威机构的私钥对应的公钥(也是默认内置在客户端),然后对“指纹”进行解密,得到证书中公钥的 Hash 值,然后再使用证书中规定的 Hash 算法,对证书中的公钥进行 Hash 运算,得到自己计算出来的 Hash 值,然后两个 Hash 值比较,如果不同,就意味着证书在传输的过程中,公钥被攻击者篡改了(如果公钥没有被篡改,两次取 Hash 绝对是相同的),如果相同,那么这个公钥就可以确定确实是服务端要发送过来的公钥,那么在之后的阶段,就可以拿着这个公钥对数据加密。

解析完证书之后,客户端会生成一个随机数 C ,用于规定之后的加密算法,同时将 C 使用公钥加密后发送给服务端。

4. 双方生成 Master Key

服务端使用自己的私钥对收到的随机数 C 解密,得到 C 的真实值。

这时客户端和服务端都拥有了两个随机数,A 、 B 和 C,并且 A 、 B 和 C 各自有客户端和服务端生成,然后双方根据这三个随机数就得到了 Master Key ,而这个 Master Key 就是后续用来进行对称加密的密钥。

5. 交流之前的验证

在之前的过程中,双方都通过秘密交换数据得到了对称加密的方法,在使用之前,还需要对此进行一遍验证过程。首先客户端会发送一段握手消息,使用已经沟通好的对称加密方式加密,同时还会使用一个统一的 Hash 算法(第一步的时候沟通的)对取握手消息的 Hash 值,发送给服务端。

服务端接收到客户端发来的验证消息之后,首先使用对称加密解密握手消息,通过相同的 Hash 算法取这个握手消息的 Hash 值,与客户端发来的 Hash 比较,相同的情况下才会继续之后的流程,否则就意味着数据在传输的过程中被篡改。

如果服务端验证无误,服务端也会以相同的方式,发送一个握手消息和它的 Hahs 值给客户端供客户端进行验证,客户端也验证完成之后就可以进行数据传输了。

当双方都验证完成之后,就说明 SSL/TLS 握手阶段完成了,之后的事情就是通过 SSL/TLS 对要传输的数据进行加密。

Hash 值的传输

在进行测试性的数据发送的过程中,需要在发送消息的同时将消息的 Hash 值发送给对方以供对方验证对称加密的正确性,那么就涉及到 Hash 值的传输问题,Hash 值可以有三种方法传输:

  1. 明文传输
  2. 使用对称加密加密之后传输
  3. 使用非对称加密加密后传输

那么应该选择哪一种方式,在这个过程中是否需要担心 Hash 值的泄漏或者篡改问题。那么就讨论下这个 Hash 值的作用,Hash 值的作用就在于校检在使用这个密钥进行对称加密的时候,双方的加密解密是否正常,即接受方会将自己解密出来的内容取一次 Hash 值,并与发送方发送过来的 Hash 对比,来检验数据是否正确(这里的正确一般是指加密解密程序是否能正常完成工作,不需要再考虑第三方篡改数据等问题),从这个角度来讲,Hash 值的传输是可以直接明文传输的,因为它被第三方截取了之后也并不能得知发送方发送的数据,被第三方篡改了之后也只是导致验证失败,并不会让客户端和服务端接收到错误的数据或者数据被泄漏。

6. 双方根据 Master Key 进行对称加密交流

由于这个 Master Key 是通过非对称加密传输的,所以其安全性有保障,而非对称加密通过证书的机制使得其本身拥有安全保障,所以这个使用 Master Key 作为密钥的对称加密也是安全的。

在上述几个流程之后,终于二者通过安全的方式协商好了对称加密的算法,所以在之后的数据传输过程中,二者并不会继续通过非对称加密的方式传输数据,而是通过对称加密的方式。原因在于,既然它们在这种条件下都是安全的,然而非对称加密相比于对称加密要多耗时很多(计算比较复杂),所以自然是选择耗时少的对称加密。