应用层协议——https协议

目录

为什么要有https协议、什么是加密解密、为什么要加密

常见的加密方式

对称加密

非对称加密

数据摘要(也被称为数据指纹)

数字签名

如何选择加密方式才能保证信息不被泄漏呢?

1、如果https协议只使用对称加密能保证信息不被泄漏吗?

2、如果https协议只使用非对称加密能保证信息不被泄漏吗?

3、如果https协议将对称加密和非对称加密组合起来使用,能保证信息不被泄漏吗?

中间人攻击

CA认证(即用于解决中间人攻击的方案)

4、如果https协议将对称加密和非对称加密和CA认证组合起来使用,能保证信息不被泄漏吗?

为什么数据摘要在网络传输的时候一定要加密形成数字签名?

学了https协议,我在代码层面上获取到的一些感悟


为什么要有https协议、什么是加密解密、为什么要加密

<<应用层协议——http协议>>一文中标题为http协议的局限性的部分说过http协议是不安全的,客户端在向服务端发起http请求时如果用户在客户端中输入过数据,因为该数据是被明文放在http请求中的,所以用户的信息很容易就泄漏了。为此,就衍生出了https协议,该协议和http协议是息息相关的,是一种能保证数据传输安全的协议。

注意HTTPS协议(HyperText Transfer Protocol Secure)不仅仅加密HTTP请求的请求正文和HTTP响应的响应正文,它实际上会将整个HTTP请求和响应都进行加密,比如还包括请求报头和响应报头。

说一下如何理解这个安全:

  • 说https协议是安全的并不是说https协议是绝对安全的,即https协议并不是不可被破解的,因为虽然当下破解的成本比较高,但随着时代的发展,机器的算力、芯片的集成程度、计算机和网络的技术都是在不断进步的,所以即使当下https协议很难被破解,但在未来就说不定了,所以才说不是绝对安全的;
  • 说https协议是安全的只是因为目前来说破解它的成本比较高(比如需要花费大量时间或者大量的金钱(电费、人工费)),只要目前破解的成本远远大于破解的收益,就可以说是安全的,因为对于大多数情况,没有收益的事情是不会有人去干的,因为没有人去干,去破解,所以也就安全了。

在上文中说过https协议和http协议是息息相关的的,怎么体现这一点呢?答案在下图的右半部分的说明里。

650d477ec77e445d992427aeed4768f8.png

根据上图可以发现,因为在调用socket接口前,数据就已经被加密了,所以在网络中传输的数据一定是被加密过的, 所以即使有恶意分子在网络中捕捉到了我们发出的信息,他也干不了什么了。

什么是加密和解密呢?

上图中所说的加密就是把明文(要传输的信息)进行一系列变换,生成密文;解密就是把密文再进行一系列变换,还原成明文。在这个加密和解密的过程中,往往需要一个或者多个中间数据,辅助进行这个过程,这样的中间数据被称为密钥(正确发音yue四声,不过大家平时都读作yao四声)。

为什么要加密呢?如下图所示。

58e1b2b4c5a04e9b804e8558fc015b5b.png

常见的加密方式

对称加密

1bac3e10a7b642e88cb9af3c8dc93318.png

可以发现,对称加密之所以被称为对称加密,就是因为被发送端用于加密的密钥和被接收端用于解密的密钥是同一把,所以称为对称。而非对称加密之所以被称为非对称加密,则是因为密钥不是同一把。

(结合下图思考)接下来例举一个简单的对称加密,它是通过按位异或实现的。假设明文数据a=1234,密钥key=8888,则加密a ^ key得到的密文b为9834,将密文发给对端后,因为^异或运算支持结合律,并且相同的数字相异或得到的数字是0,而任何数字和0相异或得到的值都还是该数字本身,所以对端拿到密文9834后,再次进行异或运算b ^ key,得到的就是原来的明文1234了。(对于字符串的对称加密也是同理,因为每一个字符串都可以表示成一个数字)当然,按位异或只是最简单的对称加密,HTTPS协议并不是通过按位异或这样的方式实现的,因为按位异或太容易破解了,整数最多只有42亿个,恶意分子捕捉到加密过的数据后,将密文和42亿个整数挨个异或一遍,进行穷举即可破解密文。

7ffb6e9f6b8b4ae4bc7aac7cb669161d.png

非对称加密

ea08031bab7c4623988f9969d288947c.png

说一下,因为非对称加密解密设计到很多数学问题比如大质数运算,所以非对称加密解密的过程会非常非常缓慢,所以别人使用公钥将数据加密后,是不能靠穷举来破解密文的,而必须靠私钥。

公钥和私钥是一个一个配队的,即使用公钥A加密的数据就只能靠私钥A解密,而不能靠私钥B解密。

可以发现,对称加密之所以被称为对称加密,就是因为被发送端用于加密的密钥和被接收端用于解密的密钥是同一把,所以称为对称。而非对称加密之所以被称为非对称加密,则是因为密钥不是同一把。

数据摘要(也被称为数据指纹)

e119146f42a54afca2931efc4f7d3034.png

数据摘要就是将数据原文通过某种哈希算法生成的一串字符串信息。不同的数据通过同一种哈希算法生成的数据摘要一定是不一样的,即使数据之间只有一个标点符号不一样,生成的数据摘要也是天差地别的。正是因为通过不同的数据生成的数据摘要一定是不一样的,就像不同的人的指纹也一定是不一样的,所以数据摘要也被称为数据指纹。

将数据原文通过某种哈希算法变成数据摘要后是无法还原的,因为哈希算法的特性就是A通过哈希算法能变成B,但B通过同样的哈希算法是无法变成A的。同时也正是因为无法通过同样的哈希算法将数据摘要还原成数据原文,即无法解密,所以从严格意义上说将数据原文通过某种哈希算法变成数据摘要并不能被算成一种加密方式。

说一下,一台主机A发起http请求时,如果http请求中的所有字段都是数据原文通过某种哈希算法变成的数据摘要,则收到该http请求的主机B是不需要也无法将数据摘要还原成数据原文的。有人可能会说【收到该http请求的主机B不将数据摘要还原成数据原文那它怎么知道原文是什么呢?】,这里笔者想说的是,收到该http请求的主机B的确是无法知道原文是什么的,但该主机B本来的目的就不是拿到原文,它是不需要知道原文是什么的,所以主机A发起http请求时才选择了将数据原文变成数据摘要。那哪些应用场景需要将数据原文变成数据摘要呢?如下。

举个例子,百度网盘有一种秒传功能,比如我下载了一个4G的美国队长,我想把他保存起来,于是将它上传到百度网盘,上传的时候发现4个G的内容在1到2秒内就上传完毕了,这是怎么回事呢?对于一个网盘而言,全国是有很多人都在使用它的,别人也会上传很多资源,可能我上传的美国队长这个视频别人已经早就上传过了,因为同样的资源是不需要在网盘中存2份的,会浪费网盘服务端进程所在的主机的磁盘空间,所以别人既然已经上传过了,我再上传时就不会真的上传,而是走个形式,于是1到2秒内就上传完毕了。那网盘是如何判断出我上传的美国队长和别人上传的美国队长是同一个视频的呢?所有用户在通过网盘客户端向网盘服务端上传资源时,首先网盘客户端对每个资源都会根据资源的一些数据和属性信息生成数据摘要,然后向网盘服务端发起一个包含了这个数据摘要的http请求(并不包含资源本身),如果网盘服务端在收到http请求并截取出这个数据摘要后,发现该数据摘要在服务端的专用于保存数据摘要的文件A中不存在,则将该数据摘要保存在服务端的文件A里,并向网盘客户端发起一个http响应表示允许上传该数据摘要对应的资源,这时上传的时间就不只是1到2秒了,而是几十分钟甚至更久了;反之如果发现该数据摘要在服务端的专用于保存数据摘要的文件A中存在,则表示该资源别人已经上传过了,则向网盘客户端发起一个http响应表示不允许你真的上传该数据摘要对应的资源,而只让你走个形式,于是上传时1到2秒就上传完毕了。

根据这个例子可以发现,因为网盘服务端压根不需要知道数据摘要的原文是什么,只需要拿着客户端发来的数据摘要和保存在网盘服务端本地的数据摘要进行比对即可完成后序业务,所以网盘服务端不需要对客户端发来的数据摘要进行解密,所以网盘客户端在发起http请求时才选择了将数据原文变成数据摘要。(额外说一下,可以发现基于网盘客户端与网盘服务端的工作模式,当使用网盘的人越来越多时,往网盘上上传资源的效率是一定会越来越高的,因为人关注的东西一定或多或少会有重叠,随着人越来越多,你上传的资源被前人已经上传过的可能性就越来越大,所以秒传的可能性就越来越大了,所以效率就越来越高了)

再举个例子,在公司上班后注册自己的员工账号时,如果直接将密码明文保存在公司的数据库中,这是不太安全的,因为公司的数据库可能因为防护不严或者公司内部人员想要报复公司故意泄漏导致数据库里所有员工的密码信息泄漏,所以一般来说正规的公司都是不会在员工进行注册时把员工输入的密码原文保存在数据库里的,而是等员工在客户端中输入密码原文后,客户端拿着该密码通过某种哈希算法生成一个数据摘要,然后给服务端发起一个包含【该员工账号】和【该员工密码对应的数据摘要】的http请求,等服务端收到该http请求并将其中的【员工账号】和【员工密码对应的数据摘要】截取出来并保存在数据库后,就会给客户端发起一个状态码为3XX的http响应让客户端重定向访问员工首页或者其他页面表示注册成功。往后用户在客户端登录时,用户在客户端输入员工的账号密码后,客户端也会拿着员工的密码通过同样的哈希算法将密码转化成数据摘要,然后给服务端发起一个包含【该员工账号】和【该员工密码对应的数据摘要】的http请求,等服务端收到该http请求并将其中的【员工账号】和【员工密码对应的数据摘要】截取出来后,服务端进程就会去访问数据库进行比对,看看数据库中这个员工账号对应的【员工密码的数据摘要】是否和客户端发来的http请求中的数据摘要匹配,如果能匹配,则服务端就会给客户端发起一个状态码为3XX的http响应让客户端重定向访问员工首页或者其他页面表示登录成功;如果不能匹配,则服务端发来的http响应就是让客户端不要重定向访问任何页面,而是依然访问登录页面,然后在登录页面提示登录失败即可,示意让用户重新登录。

根据这个例子可以发现,因为服务端压根不需要知道数据摘要的原文是什么,只需要拿着客户端发来的数据摘要和保存在数据库中的数据摘要进行比对即可完成后序业务,所以服务端不需要对客户端发来的数据摘要进行解密,所以客户端在发起http请求时才选择了将数据原文变成数据摘要。(额外说一下,因为公司数据库中不会存储密码原文,而只存储密码原文对应的数据摘要,所以即使公司的数据库泄漏,别人也只能看见密码对应的数据摘要是什么,而无法知道密码原文是什么,也就不会导致用户的私密信息(好像说用户使用密码的习惯更为贴切)泄漏了;还有一点,虽然上文中说数据库中只存在用户的密码对应的数据摘要、不存在密码的原文,好像在说除了用户自己,没人知道该用户的密码是多少,但其实并不一定是这样的,因为公司如果想拿到你的密码原文是很容易做到的,比如你在注册时输入密码后,它可以先把密码保存起来,然后再通过密码生成数据摘要并把数据摘要放到数据库中,所以只能保证公司的数据库中是不存在密码原文的,但无法保证公司没有将你的密码原文给记录下来)

数字签名

将上文所讲的数据摘要通过任何一种加密方式(不包括再次通过某种哈希算法将数据摘要再变成另一个数据摘要这种方式,这是因为这种方式无法解密,所以严格意义上并不是一种加密方式)进行加密形成密文后,该密文就是数字签名。

如何选择加密方式才能保证信息不被泄漏呢?

1、如果https协议只使用对称加密能保证信息不被泄漏吗?

8a67ab69a3b2443c915a7c0f2bbc27ff.png

如上图,假如客户端和服务端都已经有同一个密钥,那么客户端在给服务端发起http请求时,就会先把http请求中的所有字段全部通过客户端的密钥进行加密,然后再发送给服务端,服务端收到该http请求后,服务端再通过自己的密钥将http请求中的所有字段进行解密。这样一来,即使中途有中间人捕捉到了客户端发送的http请求,但因为中间人没有密钥,所以它也不知道http请求的内容是什么。

说一下,乍一看好像上一段这样是没有问题的,能完成保密功能,但实际并不然,因为在上一段开头处所说的【假如客户端和服务端都已经有同一个密钥】这种情况在实际中是不可能存在的:

  • 举个例子,为了让客户端和服务端之间传输的数据不被泄漏,于是我们让密钥给这些信息加密和解密,但问题在于双方如何拿到同样的密钥呢?可以靠客户端或者服务端中的任意一方给另一方发送密钥信息。但问题来了,密钥这个信息也是不能明文在网络中传输的,否则第三方就能获取到密钥,这样一来即使后序客户端和服务端之间传输的数据经过了密钥加密,但因为第三方也有密钥,所以也能解密,这就等于密钥就完全没有了意义,既起不到防止数据泄漏的作用,还略微增加了客户端和服务端所在的两台主机的负担(加密解密是需要CPU完成相关计算的,说略微增加负担是因为对称加密的算法比较简单),所以密钥也需要先通过密钥2进行加密,然后加密后的密钥才能在客户端与服务端之间传输。一方通过密钥2给密钥加密是很简单的,但问题在于另一方该如何得到密钥2进行解密拿到密钥,思考后好像也没有什么好的办法,也只能靠客户端或者服务端中的任意一方给另一方发送密钥2的信息。可以发现这就成了一个套娃,最后导致问题没法解决。
  • 再举个例子,既然上一段的方式(即靠客户端或者服务端中的任意一方给另一方发送密钥信息)不可行,那能不能这样,我在客户端所在的主机和服务端所在的主机上都预置上密钥信息,这样一来对称加密这种方式不就能保证信息不被泄漏了嘛?的确,是能保证了,但这样的做法有一个很大的问题,即你选择给哪些主机上预置呢?一般来说如果选择预置,则全球所有的主机都需要预置,那黑客的电脑是也会预置,既然黑客的电脑上也预置了密钥,那密钥一样会失去意义,所以这种方法也是不可行的。

除了上面所说的问题外,如果https协议只使用对称加密还会导致一个问题:服务器同一时刻是会给很多客户端提供服务的,这么多客户端,每个客户端用的秘钥都必须是不同的(因为如果是相同的,那密钥就太容易扩散了,即黑客拿到一个客户端A与服务端A的密钥1就相当于拿到了客户端B与服务端B的密钥2),因此服务端就需要维护记录好自己和每个客户端之间的密钥是哪个,这也是一个需要耗费服务端的计算机资源的事情。

综上可以发现,如果https协议只使用对称加密,那是一定保证不了信息不被泄漏的。

2、如果https协议只使用非对称加密能保证信息不被泄漏吗?

情况一如下:

5e11ceb5469f4440960ab9e7970015b5.png

(结合上图思考)如果最初只有服务端拥有私钥和公钥(即最初客户端既没有私钥也没有公钥),然后服务端把公钥以明文的方式发给客户端,客户端后序在给服务端发送http请求时就先把http请求通过公钥加密了再发,这样即使有第三方在中途捕捉了这个http请求,因为第三方没有私钥,所以第三方也不知道http请求中的数据是什么,只有拥有私钥的服务端在收到http请求后,才能通过私钥将http请求进行解密,才能获取http请求中的数据。

但上一段这样的方式有一个问题,即只能保证(实际上也是不能保证的,还是有安全问题,原因会在下文中说明)客户端发给服务端的http请求不被破解,无法保证服务端发给客户端的http响应不被破解,因为如果此时服务端给客户端发送http响应,只能通过私钥将http响应进行加密(因为客户端只有公钥,公钥是无法对服务端通过公钥进行加密的http响应进行解密的,所以服务端只能通过私钥将http响应进行加密),这样客户端收到加密过的http响应后才能通过公钥进行解密,问题来了,因为最初服务端是以明文的方式把公钥发给客户端的,毕竟公钥本来就是所有人可见的,这就会导致中间人也能获取到公钥,那么加密后的http响应也就能被中间人破解,导致http响应中的数据泄漏了。

综上可以发现,如果https协议只使用非对称加密,则只能保证(实际上也是不能保证的,还是有安全问题,原因会在下文中说明)主机A给主机B发信息时信息不被泄漏,而无法保证主机B给主机A发信息时信息不被泄漏,所以本种方法也是不可行的。

情况二如下:

0b33f17c6aba43c5b7433509a313d119.png

(结合上图思考)如果最初服务端和客户端都拥有私钥和公钥,比如服务端拥有的是私钥S和公钥S、客户端拥有的是私钥C和公钥C,然后客户端和服务端互相明文发送各自的公钥给对方,以交换公钥,此后客户端给服务端发http请求时先用公钥S对http请求加密,再发送,则该http请求只能由服务端解密,因为只有服务端有私钥S;此后服务端给客户端发http响应时也先用公钥C对http响应加密,再发送,则该http响应只能由客户端解密,因为只有客户端有私钥C。

可以发现上一段这样似乎没有漏洞,似乎不会导致http请求或者http响应中的数据泄漏(再次强调一遍,上文中说过对http请求或者响应进行加密是会对其中的所有字段进行加密的,而不仅仅是请求正文和响应正文,所以这里所说的数据表示http请求或者http响应中的所有字段),但实际上还是存在安全问题的,原因在下文中再说明。说一下,除了安全问题以外,这种方式的效率也是很低的,因为上文中说过非对称加密因为设计到大质数运算,所以导致该算法极其复杂且耗时,对比上文中的情况一,情况二也就是当前这里还使用了两次非对称加密,所以就更耗时了。

综上可以发现,本种方法也是不可行的。

3、如果https协议将对称加密和非对称加密组合起来使用,能保证信息不被泄漏吗?

75b63826d0374016ad76f54cc25d4a3f.png

(结合上图思考)如果最初服务端只拥有私钥S和公钥S,客户端只拥有对称密钥C,则首先让服务端给客户端明文发送自己的公钥S,然后客户端再通过收到的公钥S对自己持有的对称密钥C信息进行加密并将加密后的对称密钥C信息发给服务端,此时因为第三方没有私钥S,所以即使捕捉到了加密后的对称密钥C信息,也无法解密破解进而获取到对称密钥C,当服务端收到该加密后的对称密钥C信息并通过私钥C进行解密后,服务端就获取到了对称密钥C,此时除了客户端和服务端,已经没有其他人知道对称密钥C了,所以往后客户端与服务端就可以通过对称密钥将http请求和http响应进行加密和解密了,其他主机(或者说设备)因为不知道对称密钥C,所以即使截获http请求或者http响应也没有意义。

由于对称加密的效率比非对称加密高很多,因此像当前这种【只是在开始阶段传递对称密钥C的时候使用了一次对称加密,后续的传输仍然使用对称加密】的方式,是能极大提高效率的。

说一下,虽然上面已经比较接近真正的答案了,但本种方式依旧有安全问题,原因在下文中再说明原因。正是因为本种方法依然有安全问题,所以本种方法也是不可行的。

中间人攻击

在上文的【2、如果https协议只使用非对称加密】和【3、如果https协议将对称加密和非对称加密组合起来使用】部分中说过,这些方法看上去是没有安全问题的,但实际上还是存在安全问题,之前在上文中咱们说会在下文中再说明原因,现在正是时候了,所以咱们就来挨个举例说明为何存在安全问题。

先说说【2、如果https协议只使用非对称加密】

5e11ceb5469f4440960ab9e7970015b5.png

如上图是上文中讲解【2、如果https协议只使用非对称加密】时的情况一的流程图。当时我们认为这种情况下,从客户端到服务端的单向通信是安全的,理由是服务端将公钥明文发给客户端后,客户端给服务端发http请求时就通过该公钥进行加密,因为中间人没有私钥,所以无法破解加密过的http请求。现在我们就要证明其实从客户端到服务端的单向通信都不是安全的,举个例子,在客户端向服务端明文请求公钥(即发起一个http请求)后,当服务端把公钥明文包含在一个http响应里发给客户端时,如果此时中间人半路截取了这个http响应,并把其中的公钥替换成中间人的公钥M后再把http响应发给客户端(注意中间人捕捉http请求或者响应时,他不光可以看到其中的数据,他还是可以篡改其中的数据的),则客户端往后就会通过公钥M给发给服务端的http请求进行加密,这样中间人捕捉到该http请求后,因为中间人有私钥M,所以就能破解http请求了,所以可以看到这种情况下从客户端到服务端的单向通信都是不安全的。

0b33f17c6aba43c5b7433509a313d119.png

如上图是上文中讲解【2、如果https协议只使用非对称加密】时的情况二的流程图。当时我们认为这种情况下不管是客户端给服务端发送的http请求,还是服务端给客户端发送的http响应,它们都是无法被中间人破解的。现在我们就要证明其实都是可以破解的,举个例子,当客户端把公钥C明文包含在http请求中发给服务端时,如果此时有中间人半路截取了这个http请求,并把其中的公钥C替换成中间人的公钥M后再把http请求发给服务端,因为服务端并没有辨别能力,所以服务端就以为收到的公钥M是客户端给它发的,后序服务端给客户端发http响应时就会通过公钥M对http响应做加密,这样一来因为中间人有私钥M,所以中间人捕捉到http响应后就能破解该http响应了;同理,当服务端把公钥S明文包含在http响应中发给客户端时,如果此时有中间人半路截取了这个http响应,并把其中的公钥S替换成中间人的公钥M后再把http响应发给客户端,因为客户端并没有辨别能力,所以客户端就以为收到的公钥M是服务端给它发的,后序客户端给服务端发http请求时就会通过公钥M对http请求做加密,这样一来因为中间人有私钥M,所以中间人捕捉到http请求后就能破解该http请求了。综上也就可以发现,不管是客户端给服务端发送的http请求,还是服务端给客户端发送的http响应,它们都是可以被破解的。

再说说【3、如果https协议将对称加密和非对称加密组合起来使用】

75b63826d0374016ad76f54cc25d4a3f.png

如上图是上文中讲解【3、如果https协议将对称加密和非对称加密组合起来使用】时的流程图。当时我们认为这种情况下不管是客户端给服务端发送的http请求,还是服务端给客户端发送的http响应,它们都是无法被中间人破解的。现在我们就要证明其实都是可以破解的,举个例子,客户端向服务端明文请求公钥S后(即发起一个http请求后),服务端把公钥S明文包含在http响应发给客户端时,此时如果有中间人半路截取了这个http响应,并把其中的公钥S替换成中间人的公钥M后再把http响应发给客户端(注意中间人捕捉http请求或者响应时,他不光可以看到其中的数据,他还是可以篡改其中的数据的),因为客户端并没有辨别能力,所以客户端就以为收到的公钥M是服务端给它发的,后序客户端给服务端发送对称密钥C时就会通过公钥M给对称密钥C加密,这样一来因为中间人有私钥M,所以中间人捕捉到这条加密过的对称密钥C后就能解密、进而拿到对称密钥C了,中间人自己拿到对称密钥C后,再把对称密钥C通过公钥S加密并发给服务端(因为最初服务端给客户端发公钥S是明文发送的,所以中间人是能获取到公钥S的),让服务端通过私钥S解密后也获取到对称密钥C,往后因为客户端给服务端发http请求时会通过对称密钥C进行加密、服务端给客户端发http响应时也会通过对称密钥C进行加密,所以中间人是可以将它们都进行破解的(因为中间人也有对称密钥C),所以这就是在上文中说本种方法还是存在安全问题的原因。

总结

观察上面的几个不同场景,我们发现中间人能成功破解http请求和http响应的本质原因都是1、中间人能对http请求和http响应中的数据做篡改。2、客户端无法分辨包含在http响应中的密钥是否是服务端发过来的;服务端无法分辨包含在http请求中的密钥是否是客户端发过来的。

CA认证(即用于解决中间人攻击的方案)

在标题为中间人攻击的总结部分中说过,中间人能成功破解http请求和http响应的本质原因都是1、中间人能对http请求和http响应中的数据做篡改。2、客户端无法分辨包含在http响应中的密钥是否是服务端发过来的;服务端无法分辨包含在http请求中的密钥是否是客户端发过来的。所以CA认证想要解决掉中间人能成功破解http请求和http响应的问题,则就要针对这两个原因,即CA认证要让客户端能分辨出包含在http响应中的密钥是否是服务端发过来的;服务端能分辨出包含在http请求中的密钥是否是客户端发过来的。如何做到呢?答案会在下文中慢慢揭晓。

(如上图就是服务端申请到的数字证书的样例)服务端在使用HTTPS协议前,需要向CA机构申领一份数字证书,申请证书的时候,需要在特定平台申请,这时服务端会生成一对密钥,即公钥和私钥,其中公钥会随着CSR文件(即申请数字证书所需的申请文件)一起发给CA机构进行权威认证,私钥则是服务端自己保留。数字证书里含有证书申请者信息、服务端的公钥信息等,服务端把证书传输给客户端后,客户端从证书里即可获取公钥,同时因为证书就如身份证一样,所以证书就可以证明夹在证书里的公钥的权威性(如果目前体会不到这个权威性,不要担心,是正常的,如果能体会到才不正常,下文中会再次深度理解)。

问题:上一段中说服务端需要向CA机构申领一份数字证书,那CA机构是如何给服务端生成一份证书的呢?

答案:如上图就是一个证书的构成,先说一下,在上图中我们还说明了证书中的数字签名是如何生成的,这里再强调一遍。CA机构拥有自己的私钥A和公钥A,也拥有一些内置的哈希算法,先通过CA机构的哈希算法将服务端上传的申请信息变成数据摘要,然后再把数据摘要通过CA机构的私钥加密即可形成数字签名。将服务端上传的申请信息变成数字签名后,再把申请信息原文和数字签名放在一起就生成了一份证书,然后就可以将证书发给服务端了。

走到这里,我们就知道了服务端是需要向CA机构申领一份数字证书的,也知道了CA机构是如何给服务端生成一份证书并将证书发给服务端的,接下来我们就来说明一下证书起了什么作用。

75b63826d0374016ad76f54cc25d4a3f.png

把上文中存在安全问题的方案【3、如果https协议将对称加密和非对称加密组合起来使用】拿来举例,如上图就是该种方案的流程图。在当时,我们选择直接将服务端的公钥S明文包含在http响应中发送给客户端,导致http响应可能被中间人捕捉到并篡改其中的数据,即把公钥S换成中间人的公钥M,进而导致客户端发给服务端的信息泄漏;而现在我们的服务端得到了CA机构发下来的证书,证书中是包含了服务端的公钥S的,所以服务端往后就无需单独将公钥S发给客户端,而是直接把证书发给客户端即可,这样能保证客户端收到的密钥一定是服务端发的公钥S,而不是中间人发的公钥M,这就是证书起到的作用。凭什么敢保证呢?

首先要知道,客户端在收到证书后是会检测证书是否受到过篡改的,所以证书中的任意内容被中间人篡改后,客户端都是能够识别到的,这时客户端就会停止和服务端进行通信。凭什么敢说能识别到呢?

客户端检测证书是否受到过篡改的方式是:客户端在收到该证书后,首先会将证书里的明文信息通过同样的哈希算法(和谁同样的哈希算法呢?CA机构当时给服务端生成证书时,证书中的数字签名部分就是CA机构先将申请信息原文通过一种哈希算法变成数据摘要,再将数据摘要通过CA机构的私钥加密得到的,所以就是和这里同样的哈希算法)变成数据摘要,然后将证书里的数字签名通过CA机构的公钥(CA机构的公钥会被内置进客户端里)解密得到数据摘要(强调一下,客户端是只会用CA机构的公钥对证书里的数字签名做解密的,而不会用其他密钥对数字签名做解密),然后将两份数据摘要进行比对,如果是相同的,则说明证书没有被中间人篡改,证书是可信的;如果是不相同的,则说明已经被中间人篡改过了,证书不可信,客户端停止向服务端通信。所以如果是情况1,即中间人只改明文信息部分、不改数字签名部分,则因为上文中说过不同的信息,即使只有一个标点符号不同,通过同一个哈希算法形成的数据摘要都是天差地别的,所以客户端收到证书后,把证书中的受到篡改的明文信息通过哈希算法变成数据摘要后,再把证书中的数字签名也通过CA机构的公钥解密变成数据摘要后,一比对就会发现两个数据摘要的值是不同的,所以也就无法通过检测了。                         

如果是情况2,即中间人不改明文信息部分、只改数字签名部分,则分两种情况,如果没有通过CA机构的公钥将数字签名解密就直接将数字签名修改了,那证书被客户端收到后,客户端再拿着CA机构的公钥将篡改过的数字签名解密,解出来的数据摘要肯定是和【证书中的明文信息通过哈希算法变成的数据摘要】是不同的(举个例子,原来的明文信息是a,数字签名是x,a经过哈希算法会变成数据摘要b,x经过解密也会变成数据摘要b,但数字签名被改成y后,y经过解密就不可能变成b了),所以也就无法通过检测了;如果先通过CA机构的公钥将数字签名解密得到数据摘要,再将数据摘要修改,则因为中间人没有CA机构的私钥,也就没法把修改过的数据摘要重新加密变成数字签名,等到服务端收到这个证书后,服务端拿着CA机构的公钥对这个已经不是数字签名的数字签名解密时,解出来的数据摘要也肯定和【数据原文通过哈希算法形成的数据摘要】是不同的,所以也就无法通过检测了。举个例子,原来的明文信息是a,数字签名是x,a经过哈希算法会变成数据摘要b,x经过解密也会变成数据摘要b,两个数据摘要都等于b,所以证书就能通过客户端的检测。现在数字签名先被解密变成数据摘要b后,再被变成了数据摘要c,然后可能因为中间人发现没有CA机构的私钥把数据摘要c重新变成数字签名,从而再经过一番胡乱操作后把数据摘要从c变成了d,但因为只有x经过解密才会变成数据摘要b,所以d经过解密就不可能变成b了,既然一个数据摘要等于b,另一个数据摘要不等于b,那也就没法通过客户端的检测了。​​​​

如果是情况3,即中间人既修改明文信息部分、又修改数字签名部分,比如最初证书中的数据明文是a,数字签名是x,当数据明文的值被中间人从a修改成b后,如果最后客户端对证书做检查时,b经过哈希算法会变成数据摘要c,那么只要客户端发现通过CA机构的公钥对某个数字签名解密得到的数据摘要的值也等于c,证书就能通过检测,那么也就是说中间人只要推导出该数字签名是多少,然后把证书中的数字签名从x换成这个数字签名即可让证书通过检测,这样一来就等于说是中间人即使把证书中的内容改了,也能让该证书通过客户端的检测,但问题恰好在于想要推导出该数字签名是多少就得知道CA机构的私钥(因为通过CA机构的公钥对数字签名做解密才能得到数据摘要c,所以想要反推数字签名,也就只能通过CA机构的私钥对数据摘要做加密才能得到数字签名了),而CA机构的私钥是不可能被中间人知道的,所以是无法在改了数据明文后,妄图通过把数字签名也改了从而通过客户端的证书检测的,最后不管如何,比对两个数据摘要时都是会发现两个数据摘要是不相等的,所以也就无法通过检测了。

如果是情况4,即中间人发现既然所有的篡改行为都不可行,那就不篡改证书了,中间人直接把证书整个给调包了,比如中间人先向CA机构申领真的证书,然后用自己申请的证书进行调包,因为中间人的证书没有被篡改,所以按理来说客户端就应该能通过检测,又因为中间人的证书中包含的公钥M是中间人的,这样当客户端给服务端发包含对称密钥C的http请求前就会先用公钥M进行加密,发送后,又因为中间人又有私钥M,所以中间人就能获取到对称密钥C,往后客户端和服务端互相通信时再通过对称密钥C加密时,这些信息在中间人眼里也就不是秘密了。走到这里可以发现调包证书貌似能通过客户端的检测,那这样到底行不行呢?答案是也不可行的,因为客户端在检测证书时,不光检测【通过证书中的数字签名得到的数据摘要】和【通过证书中的信息原文得到的数据摘要】是否相等,还要检测包含在证书的明文信息部分中的域名等服务端认证信息的,你现在域名变成了中间人的域名,我客户端当然能分辨出来,所以调包这种方式也是无法通过客户端的检测的。

综上穷举了中间人篡改证书或者调包证书的所有可能发生的情况,可以发现不管怎么造,只要中间人敢篡改证书或者调包证书,客户端就一定能检测出来,所以上文中才敢说“证书中的任意内容被中间人篡改后,客户端都是能够识别到的”。

既然中间人篡改证书中的任意内容都会被客户端识别到,所以也就能保证客户端收到的包含在证书中的密钥一定是服务端发的公钥S,而不是中间人发的公钥M了,这就是上文中说敢保证服务端把证书直接发给客户端时,客户端收到的密钥一定是服务端发的公钥S,而不是中间人发的公钥M的原因了。

在讲解标题为CA认证的部分时,我们在第一段中就说了,CA认证想要解决掉中间人能成功破解http请求和http响应的问题,则CA认证要让客户端能分辨出包含在http响应中的密钥是否是服务端发过来的,同时让服务端也能分辨出包含在http请求中的密钥是否是客户端发过来的。走到这里我们发现因为证书的存在,客户端已经能分辨出包含在http响应中的密钥(即服务端的公钥)是否是服务端发过来的了,比如如果客户端检测到证书被篡改,则说明http响应是中间人发的,那位于http响应中的密钥也就不一定是服务端发的了;如果客户端检测到证书没被篡改,则说明http响应是服务端发的,那位于http响应中的密钥肯定也是服务端发的了。同时因为客户端拿到了服务端发来的包含在http响应中的证书中的密钥(即服务端的公钥),因为客户端发送包含对称密钥C的http请求时会通过服务端的公钥加密,而只有服务端的私钥能够破解该http请求,中间人是没有服务端的私钥的,所以中间人就没法破解http请求并篡改http请求的原文,而只能把加密过的http请求(加密过的http请求本质是一长串字符串)的内容稍作修改,这就没什么意义,只能让服务端收到该加密过的http请求后,解密时解出来的东西啥也不是,所以服务端也就能分辨出包含在http请求中的密钥(即客户端的对称密钥C)是否是客户端发过来的了,比如如果服务端发现拿着服务端的私钥解密收到的http请求时解出来的东西啥也不是,则说明加密过的http请求这个密文中途受到过篡改,也就证明该http请求不是客户端发来的;再比如如果服务端发现拿着服务端的私钥解密收到的http请求时解出来的东西就是客户端的对称密钥C,则说明加密过的http请求这个密文中途没有受到篡改,也就证明该http请求就是客户端发来的。所以服务端收到一个http请求时,就有了一个判断该http请求是否是客户端发来的判断标准,所以服务端也就能分辨出包含在http请求中的密钥(即客户端的对称密钥C)是否是客户端发过来的了。综上所述,既然通过CA认证能够让客户端能分辨出包含在http响应中的密钥是否是服务端发过来的,同时也能让服务端分辨出包含在http请求中的密钥是否是客户端发过来的,那根据本段开头处所说,CA认证也就解决了中间人能成功破解http请求和http响应的问题,也就解决了在上文标题为中间人攻击的部分中所说的全部场景下的问题了。

4、如果https协议将对称加密和非对称加密和CA认证组合起来使用,能保证信息不被泄漏吗?

流程图如上所示,因为当前这种方式就是在上文中的方式【3、如果https协议将对称加密和非对称加密组合起来使用】的基础上再加上了CA认证这个操作,又因为在讲解CA认证时我们证明过一点,即“引入证书后,只要中间人敢篡改证书或者调包证书,客户端就一定能检测出来,进而也就能保证客户端收到的包含在证书中的密钥一定是服务端发的公钥S,而不是中间人发的公钥M”,所以当前这种方式就解决了上文中的方式【3、如果https协议将对称加密和非对称加密组合起来使用】中存在的安全问题(如果忘记了是什么安全问题,就回看该部分内容),所以当前这种方式就已经是安全的了,中间人无法再破解客户端发给服务端的http请求,也无法破解服务端发给客户端的http响应。说一下,当前这种方式也就是https协议真正工作在客户端和服务端的工作方式。

为什么数据摘要在网络传输的时候一定要加密形成数字签名?

在上文中我们讲过,客户端检测证书是否受到过篡改的方式是:客户端在收到该证书后,首先会将证书里的明文信息通过同样的哈希算法(和谁同样的哈希算法呢?CA机构当时给服务端生成证书时,证书中的数字签名部分就是CA机构先将申请信息原文通过一种哈希算法变成数据摘要,再将数据摘要通过CA机构的私钥加密得到的,所以就是和这里同样的哈希算法)变成数据摘要,然后将证书里的数字签名通过CA机构的公钥(CA机构的公钥会被内置进客户端里)解密得到数据摘要(强调一下,客户端是只会用CA机构的公钥对证书里的数字签名做解密的,而不会用其他密钥对数字签名做解密),然后将两份数据摘要进行比对,如果是相同的,则说明证书没有被中间人篡改,证书是可信的;如果是不相同的,则说明已经被中间人篡改过了,证书不可信,客户端停止向服务端通信。

既然最后检测证书时,还是要把明文信息和数字签名都想办法转化成数据摘要后再进行比对,那为什么不一开始就在证书中放明文信息和通过明文信息形成的数据摘要呢?干嘛要多此一举把数据摘要再次加密形成数字签名呢?答案如下。

如果证书中保存的是明文信息和通过明文信息形成的数据摘要,那么中间人篡改证书是非常方便的,并且篡改后还能让客户端检测不出来。举个例子,最初证书中的明文信息是a,数据摘要是x,中间人将明文信息从a修改成b后,先通过哈希算法计算出b的数据摘要y,然后把证书中的数据摘要直接从x换成y即可,这样一来,等客户端收到证书进行检测时,发现通过明文信息b形成的数据摘要的确就是y,证书中保存的数据摘要的值也是y,二者相等,客户端的检测也就通过了。可以发现,如果不将证书中的数据摘要加密让它形成数字签名, 那客户端也没有对数字签名解密的必要,这种情况下证书太容易被篡改了,而且客户端根本检测不出来证书被修改了,所以这就是数据摘要在网络传输的时候一定要加密形成数字签名的原因。

学了https协议,我在代码层面上获取到的一些感悟

<<应用层协议——http协议>>一文中的代码一样,想要让https协议在客户端和服务端中起作用,也是需要程序员在服务端和客户端中编写相关逻辑的代码的,比如上文学了那么多种加密方式,我们以后服务端和客户端在调用send前,就可以先对要发给对方的信息做加密,保证信息不被泄漏;服务端和客户端在调用recv后,就要先对读取到的密文信息解密,才能顺利读到原文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值