https小结

大家都知道,https俗称为安全的http,何谓安全?在讲https之前,我们先来看一个简单的聊天软件demo

看下面例子,我们要实现A能发一个hello消息给B:

如果我们要实现这个聊天软件,本文只考虑安全性问题,则要实现:A发给B的hello消息包,即使被中间人拦截到了,也无法得知消息的内容

如何解决安全问题?

在讲如何解决安全问题之前,我们先来看2个很重要的概念——对称加密和非对称加密

所谓对称加密,就是加密和解密都通过一个密钥进行,信息通过密钥加密成密文,通过网络传输,到达对端以后,通过密钥把密文解密成明文。对称加密算法的最大优点就是加解密速度,缺点是一旦密钥泄露,密文将非常容易被解密出明文来。

再来看看什么是非对称加密,所谓非对称,意思就是加密和解密用的秘钥是不同的,我们称这一对不同的秘钥为公钥和私钥,其中,公钥是公开的,所有人都能获得,而私钥则是不公开的。在非对称算法里,通过公钥解密的密文只有通过私钥才能解密,同样,通过私钥加密的密文,只有通过公钥才能解密。通过公钥获取私钥是非常困难的,目前只能通过暴力破解,这个涉及到大质数相乘后因数分解的数学问题,大家有兴趣可以自行了解。相对于对称加密,非对称加密算法会更加安全,但是相对应的,耗时也会比较长

使用对称加密算法传输数据

说到这个安全问题,大家脑海里出现的可能就是各种什么加密和验签,什么RSA、MD5、对称加密、非对称加密等等等等。

对,这种做法是最直接的做法,例如,AB通信,A用密钥S加密,加完密之后,发送给B,B接收了信息之后再通过密钥S解密出来,拿到信息,示例如下

通过上面的对称算法和非对称算法的解释,可以知道,这里进行的加解密过程使用的是对称加密算法

上图示例,好像问题已经完美解决了,攻击者就算拿到传输的数据,也拿不到我传输的明文。但是,大家再来看看上文提到对称加密的一个问题——一旦密钥泄露,密文将非常容易被解密出明文来。意思就是说,如果使用对称加密,密钥的管理是最大的问题。我们来看看这个密钥怎么管理,管理方法无非就是两种,一种就是配置在某个远端,A端再发一次请求获取后加密,B也获取到之后再解密;一种就是在传输的过程中传输密钥。

我们假设B为服务器,A为客户端,分析一下这2种方案

先来看看第一种,第一种形式管理密钥,会产生第三方额外的交互,所以我们不采取这种做法

既然不采用第一种方法管理密钥,我们只能采用第二种方案来管理了,我们来看看第二种有什么问题,第二种管理方法是密钥实时生成实时传输,这就产生一个问题了——密钥怎么传输?传输的过程中,万一也出现被盗取的情况,攻击者又将轻易进行信息获取了,这就产生“鸡生蛋,蛋生鸡”的问题了

使用非对称加密算法传输密钥

从上文我们了解到,密钥还是需要传输才能得到,那如何才能安全传输呢?答案是:通过非对称加密算法加密密钥进行传输

我们来看看使用非对称加密算法是如果加密密钥进行传输的,上文提到,非对称加密算法有2个密钥,一个是公钥,一个是私钥。公钥是公开的,而私钥是不公开的,在我们这个场景里,明显客户端存着公钥,服务器存着私钥。传输信息的秘钥在客户端通过公钥加密后,传输到服务器,服务器通过私钥解密出数据,即得到通信所需要的密钥。

看到这里,大家是不是有个疑问,既然可以通过非对称算法可以用来加密密钥,何不直接用非对称加密算法来加密传输的内容?

这个问题很简单,前面提到了:非对称加密相对于对称加密,耗时会比较长,虽然http是短链接,但是由于http的header里有个参数keep-alive,所以是有很大可能在一个链接里进行多次数据传输,这样一来,对称加密算法的优势就立刻体现了

总结上文,现在AB之间的交互是这样的:

PS:这下大家对书本上的一个说法——“HTTPS同时采用对称加密和非对称加密算法进行数据传输” 彻底理解了吧?

公钥的管理方式

细心的人可能已经注意到了,如果使用非对称加密算法,客户端必须要持有公钥,否则无法对信息进行加密处理,那么这个公钥是怎么获取到的呢?

一样的,管理公钥跟密钥都有2种方式,要么通过第三方获取,要么直接双方交互获得公钥。我们还是采用第二种做法——双方交互获得公钥

但是,一旦公钥被调包了怎么办?客户端获取不到正确的公钥,是会产生很大问题的,详见下图

可以看到,这里信息就被篡改了,就算不篡改,通信的私钥就泄露了

通过第三方机构解决公钥被篡改问题

公钥被调包的问题出现,是因为我们的客户端无法分辨返回公钥的人到底是中间人,还是真的服务器。这其实就是密码学中提的身份验证问题。

既然服务器需要将公钥传给客户端,这个过程本身是不安全,那么我们为什么不对这个过程本身再加密一次?可是,你是使用对称加密,还是非对称加密?这下好了,感觉又进了鸡生蛋蛋生鸡问题了。

问题的难点是如果我们选择直接将公钥传递给客户端的方案,我们始终无法解决公钥传递被中间人调包的问题。

所以,我们不能直接将服务器的公钥传递给客户端,而是第三方机构使用它的私钥对我们的公钥进行加密后,再传给客户端。客户端再使用第三方机构的公钥进行解密。

这个时候,我们的获取公钥流程就变成这样了:

PS1:看到这里,你明白颁发CA证书的HTTPS认证机构是用来干吗的了吧?

PS2:客户端是浏览器,浏览器发行的时候,证书机构就已经把公钥内置到浏览器中

PS3:这里涉及到2套公私钥了,一套是用于服务器和客户端交换对称加密密钥的,一套是第三方跟我们交互的公私钥

数字签名,解决同一机构颁发的不同证书被篡改问题

看到这里,好像问题已经完美解决了,但是,攻击者是无孔不钻的,我们来看一下这种情况:

服务器在第三方认证机构做过注册,但是,攻击者也可以在第三方认证机构注册,攻击者在客户端获取公钥的时候,把服务器返回的第三方密文和公钥(其实在HTTPS领域里,这个叫证书,下文以证书代替)全部替换了,怎么办?(如下图所示)

要解决这个问题,我们首先要想清楚一个问题,辨别同一机构下不同证书的这个职责,我们应该放在哪?

只能放到客户端了。意思是,客户端在拿到证书后,自己就有能力分辨证书是否被篡改了。如何才能有这个能力呢?

我们从现实中找灵感。比如你是HR,你手上拿到候选人的学历证书,证书上写了持证人,颁发机构,颁发时间等等,同时证书上,还写有一个最重要的:证书编号!我们怎么鉴别这张证书是的真伪呢?只要拿着这个证书编号上相关机构去查,如果证书上的持证人与现实的这个候选人一致,同时证书编号也能对应上,那么就说明这个证书是真实的。

我们的客户端能不能采用这个机制呢?像这样:

可是,这个“第三方机构”到底是在哪呢?是一个远端服务?不可能吧?如果是个远端服务,整个交互都会慢了。所以,这个第三方机构的验证功能只能放在客户端的本地了。

客户端如何验证编号的正确性

客户端本地怎么验证证书呢?答案是证书本身就已经告诉客户端怎么验证证书的真伪。

也就是证书上写着如何根据证书的内容生成证书编号。客户端拿到证书后根据证书上的方法自己生成一个证书编号,如果生成的证书编号与证书上的证书编号相同,那么说明这个证书是真实的。

同时,为避免证书编号本身又被调包,所以使用第三方的公钥进行加密。

PS:前文提到,浏览器发行的时候,证书机构就已经把公钥内置到浏览器中,每个域名在第三方机构的公钥是不一样的

有点抽象,下面我们一步步剖析一下证书编号生成和校验过程:

1.第三方收到服务器拿证书的请求

2.第三方开始生成证书,编号的生成过程为:对证书的其他一些内容做一次MD5,然后使用该站点在第三方机构的秘钥做一次非对称加密,作为证书编号

3.客户端拿到证书后,对证书编号进行解密,再把解密出来的数据跟算法(这里是MD5)计算出来的数据比较是否一致,如果一致,说明是没问题的,如果不一致,说明证书非法

可以参考以下图片:(生成编号为上图,校验编号为下图)

PS:由于攻击者拿不到第三方的私钥,所以要伪造这个编号是非常困难的

但是第三方机构的公钥怎么跑到了客户端的机器中呢?世界上这么多机器。

其实呢,现实中,浏览器和操作系统都会维护一个权威的第三方机构列表(包括它们的公钥)。因为客户端接收到的证书中会写有颁发机构,客户端就根据这个颁发机构的值在本地找相应的公钥。

 

HTTPS的运行机制

其实上文倒过来看,就是整个HTTPS的运作机制了,总结一下,HTTPS的运作机制如下图所示

 

参考文章:http://blog.jobbole.com/110354/

 

 

 

 

posted @ 2018-10-27 20:00  无名草110  阅读(191)  评论(0编辑  收藏  举报